简体   繁体   English

你能解释一下为什么打字稿防护不起作用

[英]Could you explain why typescript guard doesn't work

With Typescript 3.1 I have got a following piece of code 使用Typescript 3.1,我得到了以下代码

type Variable = string[] | File;

function isFile(variable: Variable): variable is File {
  return (variable as File).name !== undefined;
}

function getFileFromVariables(entity: EntityInterface) {
   return isFile(this.state.variables[entity.variable])
           ? this.state.variables[entity.variable]
           : undefined;
}

const file = getFileFromVariables(someEntity);

Unfortunately, I don't know why the file is const file: string[] | File | undefined 不幸的是,我不知道为什么文件是const file: string[] | File | undefined const file: string[] | File | undefined const file: string[] | File | undefined instead of const file: File | undefined const file: string[] | File | undefined而不是const file: File | undefined const file: File | undefined

Could someone tell me why it's like this and how may I fix it? 有人可以告诉我为什么会这样,我该如何解决?

TypeScript isn't able to link together two instances of this.state.variables[entity.variable] - one that is passed into type guard and another used afterwards. TypeScript无法将this.state.variables[entity.variable]两个实例链接在一起-一个实例传递给类型保护,另一个实例随后使用。 For it, this is two unrelated queries into array, since entity.variable could be very well changed by some undercover process (or even by the type guard, if it is in the same scope), and type system isn't able to catch that. 为此,这是两个与数组无关的查询,因为entity.variable可能会被某些秘密程序(甚至在相同作用域内,甚至可以通过类型保护器)很好地更改,并且类型系统无法捕获那。

A common workaround is to use the temporary variable: 常见的解决方法是使用临时变量:

type Variable = string[] | File;

function isFile(variable: Variable): variable is File {
  return (variable as File).name !== undefined;
}

function getFileFromVariables(entity: EntityInterface) {
   const variable = this.state.variables[entity.variable];
   return isFile(variable) ? variable : undefined;
}

const file = getFileFromVariables(someEntity);

Side note: try to provide a self-contained example, in other words, an MCVE . 旁注:尝试提供一个独立的示例,即MCVE Your code was impossible to check, since we don't know neither what EntityInterface interface looks like nor what is this or this.state . 您的代码无法检查,因为我们既不知道EntityInterface接口是什么样,也不知道thisthis.state是什么。 My answer is assuming that this.state.variables is of type Variable and EnintyInterface extends {variable: number} , and it's enough for the code provided to give you the result you ask, but please, don't force us to do this assumptions. 我的回答是假设this.state.variables的类型为Variable并且EnintyInterface extends {variable: number} ,并且所提供的代码足以满足您的要求,但是请不要强迫我们执行此假设。

Your question is pretty vague. 您的问题很模糊。

Other than that, all the problems you are encountering are from non-strict mode and some other poor practices. 除此之外,您遇到的所有问题都来自非严格模式和其他一些不良实践。 I suggest you the following: 我建议您以下:

  • Add "strict": true to compilerOptions of tsconfig.json (at least temporarily, until you figure out the solution to your problem) 加入"strict": truecompilerOptionstsconfig.json (至少是暂时的,直到你找出解决问题的方法)
  • Define explicitly what you want to get from a function eg getFileFromVariables(...): File | undefined 明确定义要从函数中获取的内容,例如getFileFromVariables(...): File | undefined getFileFromVariables(...): File | undefined
  • If possible, don't use classic functions for such cases. 如果可能的话,请勿在这种情况下使用经典功能。 Instead define a type type GetFileFromVariables = (ent: EntityInterface) => File | undefined 而是定义类型type GetFileFromVariables = (ent: EntityInterface) => File | undefined type GetFileFromVariables = (ent: EntityInterface) => File | undefined , then const getFileFromVariables: GetFileFromVariables = () => ... type GetFileFromVariables = (ent: EntityInterface) => File | undefined ,然后const getFileFromVariables: GetFileFromVariables = () => ...

Then everything instantly becomes much clearer to you. 然后,一切立即变得清晰起来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM