Typescript索引属性约束检查处理原始类型而不是对象文字?

时间:2017-02-17 14:12:37

标签: typescript

有这个接口声明:

interface Thing1 {
    [key: string]: string;
    x: number;
}

打字稿在编译时会抛出错误" TS2411:属性' x'类型编号不能分配给字符串索引类型'字符串'"

听起来很合法。

但是,只要我使用对象文字作为索引类型值:

interface Foo {}
interface Thing2 {
    [key: string]: Foo;
    foo: number;
}

......它不再抱怨了,这对我来说听起来很奇怪,因为number仍然是与Foo不同的类型

有关这背后原因的任何想法吗?

注意:使用Typescript 2.1.5

2 个答案:

答案 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库中的关系类型更为自然。