Typescript 索引属性约束检查适用于原始类型但不适用于对象文字?
Posted
技术标签:
【中文标题】Typescript 索引属性约束检查适用于原始类型但不适用于对象文字?【英文标题】:Typescript indexed properties constraint checks working on raw types but not on object literals? 【发布时间】:2017-07-07 02:29:36 【问题描述】:有这个接口声明:
interface Thing1
[key: string]: string;
x: number;
Typescript 在编译时抛出错误“TS2411:类型编号的属性 'x' 不可分配给字符串索引类型 'string'”
听起来很合法。
但是,只要我使用对象字面量作为索引类型值:
interface Foo
interface Thing2
[key: string]: Foo;
foo: number;
...它不再抱怨了,这对我来说听起来很奇怪,因为 number
仍然是与 Foo
不同的类型
你知道这背后的原因吗?
注意:使用 Typescript 2.1.5
【问题讨论】:
【参考方案1】:空接口与简单类型(数字、字符串)兼容。如果你这样写,Typescript 不会抱怨:
let c: Foo = 3;
因此,在 Thing2 中,打字稿推断仍将 Foo 视为与数字兼容。但是,当索引签名是像 Thing1 中那样的字符串时,所有成员都应该是字符串(如您所述)。
【讨论】:
【参考方案2】:这是由于 type compatibility 在 TypeScript 中的工作方式:
TypeScript 中的类型兼容性基于结构子类型。结构类型是一种仅基于其成员关联类型的方法。这与名义类型不同。
所以,这行得通:
interface Foo
let f: Foo = 3;
因为 上的每个属性,
Number
上都有一个名称和类型相同的属性。
这意味着这不起作用:
interface Foo
let f: Foo = 3;
let b: number = f;
编译器抱怨let b: number = f;
:
类型 'Foo' 不能分配给类型 'number';
再次,来自文档:
TypeScript 的结构化类型系统是根据 javascript 代码的典型编写方式设计的。由于 JavaScript 广泛使用函数表达式和对象字面量等匿名对象,因此使用结构化类型系统而不是名义上的类型系统来表示 JavaScript 库中发现的各种关系要自然得多。
【讨论】:
我知道结构类型,但是,我从没想过一个数字会具有与对象字面量完全相同的“结构”(就其 API 而言)。诡异的。 :-) @Frédéric 需要明确的是,数字没有相同的结构,只是
上的每个属性在Number
上都有一个具有相同名称和类型的属性。我会澄清答案。以上是关于Typescript 索引属性约束检查适用于原始类型但不适用于对象文字?的主要内容,如果未能解决你的问题,请参考以下文章