有这个接口声明:
interface Thing1 {
[key: string]: string;
x: number;
}
打字稿在编译时会抛出错误" TS2411:属性' x'类型编号不能分配给字符串索引类型'字符串'"
听起来很合法。
但是,只要我使用对象文字作为索引类型值:
interface Foo {}
interface Thing2 {
[key: string]: Foo;
foo: number;
}
......它不再抱怨了,这对我来说听起来很奇怪,因为number
仍然是与Foo
不同的类型
有关这背后原因的任何想法吗?
注意:使用Typescript 2.1.5
答案 0 :(得分:1)
空接口与简单类型(数字,字符串)兼容。如果你这样写,打字稿不会抱怨:
function getTokens(str) {
var results = [], re = /{([^}]+)}/g, text;
while(text = re.exec(str)) {
results.push(text[1]);
}
return results;
}
var myString = "SELECT * FROM {token1} WHERE {token2}";
console.log(getTokens(myString));
因此,在Thing2中,打字稿推断仍然会看到Foo与数字兼容。但是,当索引签名是Thing1中的字符串时,所有成员都应该是字符串(如您所述)。
答案 1 :(得分:1)
这是由于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'不能分配类型'数字';
再次,从文档:
TypeScript的结构类型系统是根据JavaScript代码的编写方式设计的。因为JavaScript广泛使用像函数表达式和对象文字这样的匿名对象,所以用结构类型系统而不是名义系统来表示JavaScript库中的关系类型更为自然。