为什么以下断言有效:
interface AllRequired {
a: string;
b: string;
}
let all = {a: "foo"} as AllRequired; // No error
但这个断言给出了一个错误:
interface SomeOptional {
a?: string;
b: string;
}
let some = {a: "foo"} as SomeOptional; // Error: Property 'b' missing
我能看到的唯一区别是使接口属性之一成为可选(?
)。似乎如果所有属性都不是可选的,我可以向接口断言部分对象,但是一旦任何接口属性都是可选的,我就无法再断言部分对象。这对我来说确实没有意义,而且我一直无法找到这种行为的解释。这里发生了什么?
对于上下文:我遇到这种行为在尝试解决 React 的问题时setState()
接受部分状态对象,但是TypeScript 尚无部分类型使其与您的状态接口正常工作。作为一种解决方法,我想出了setState({a: "a"} as MyState)
并发现只要界面就可以工作MyState
字段是all不可选,但一旦失败就会失败some属性是可选的。 (将所有属性设置为可选是一种解决方法,但在我的情况下非常不可取。)
类型断言只能用于在类型与其子类型之间进行转换。
假设您声明了以下变量:
declare var foo: number | string;
declare var bar: number;
Note number
is a subtype of number | string
,表示与类型匹配的任何值number
(e.g. 3
) 也匹配number | string
。因此,允许使用类型断言在这些类型之间进行转换:
bar = foo as number; /* convert to subtype */
foo = bar as number | string; /* convert to supertype (assertion not necessary but allowed) */
相似地,{ a: string, b: string }
是一个子类型{ a: string }
。任何匹配的值{ a: string, b: string }
(e.g. { a: "A", b: "B" }
) 也匹配{ a: string }
,因为它有一个a
类型的属性string
.
相比之下,两者都没有{ a?: string, b: string }
or { a: string }
是另一个的子类型。
一些值(例如{ b: "B" }
)仅匹配前者,其他(例如{ a: "A" }
) 仅匹配后者。
If you really需要在不相关的类型之间进行转换,您可以通过使用通用的超类型(例如any
)作为中间体:
let foo = ({ a: "A" } as any) as { a?: string, b: string };
规范中的相关部分是4.16 类型断言:
在 e 形式的类型断言表达式中,e 由 T 进行上下文类型化(第 4.23 节),并且结果类型为e需要可分配给 T,或者 T 需要可分配给 e 的结果类型的扩展形式,否则会发生编译时错误。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)