【问题标题】:Typescript assigning an interface or a type to a Record<string, string>将接口或类型分配给 Record<string, string> 的打字稿
【发布时间】:2021-03-06 06:51:59
【问题描述】:

阅读this questionthis article 后,我仍然对interfacetype 之间的细微差别感到有些困惑。

在本例中,我的目标是将一个简单对象分配给更广泛的Record&lt;string, string&gt; 类型:

interface MyInterface {
  foobar: string;
}

type MyType = {
  foobar: string;
}

const exampleInterface: MyInterface = { foobar: 'hello world' };
const exampleType: MyType = { foobar: 'hello world' };

let record: Record<string, string> = {};

record = exampleType;      // Compiles
record = exampleInterface; // Index signature is missing

Try it

使用type 声明我的对象时可以进行赋值,但使用interface 声明类似的对象时则不能。它说缺少索引签名,但根据我对索引签名的(有限)理解,MyTypeMyInterface 实际上都没有。

最后一行不编译而上一行编译的原因是什么?

【问题讨论】:

  • 有趣。我没有意识到这一点,但它确实是有道理的。 { foobar: string } 类型是您可以接收的下限。它基本上意味着“任何具有至少foobar的对象”。显然,制作成一种类型保留了这种意义。但是,对于 interface 而言,语义是不同的,它可能没有任何其他键。这有点奇怪,因为这两个变量都不会接受要添加的名为 hello 的新密钥。所以它们的可分配性不同。

标签: typescript


【解决方案1】:

Record&lt;string, string&gt;{ [key: string]: string } 相同。仅当该类型的所有属性都已知并且可以根据该索引签名进行检查时,才允许将子集分配给此索引签名类型。在您的情况下,来自exampleType 的所有内容都可以分配给Record&lt;string, string&gt;。这只能检查对象字面量类型,因为对象字面量类型一旦声明就不能更改。因此,索引签名是已知的。

来源:https://github.com/microsoft/TypeScript/pull/7029

相反,接口在你声明它们的那一刻并不是最终的。由于声明合并,总是有可能向同一接口添加新成员。

【讨论】:

    猜你喜欢
    • 2022-06-11
    • 2021-09-21
    • 2022-08-14
    • 1970-01-01
    • 2022-01-17
    • 2019-04-10
    • 2019-07-09
    • 1970-01-01
    • 2021-04-24
    相关资源
    最近更新 更多