【问题标题】:How to mix index signature with known properties?如何将索引签名与已知属性混合?
【发布时间】:2020-12-05 08:47:46
【问题描述】:

假设接口具有一些已知属性及其类型,并且可以具有其他具有未知键和一些其他类型的属性,例如:

interface Foo {
  length: number;
  [key: string]: string;
}

const foo : Foo = {
  length: 1,
  txt: "TXT",
};

TS 错误:

“数字”类型的属性“长度”不能分配给字符串索引类型“字符串”。

这样的界面应该怎么打?

【问题讨论】:

标签: typescript index-signature


【解决方案1】:

[key: string]: string; 这可以防止Foo 接口没有字符串属性(在您的示例中为number)。

您可以做的是将两个接口中的已知和未知属性分开,并将您的目标类型定义为联合类型,如下所示:

interface Foo {      
  length: number;
}

interface Bar {
    [key: string]: string ;
}

type FooBar = Foo | Bar;

const foo : FooBar = {
  length: 1, // its ok defined in foo
  txt: "TXT", // string is ok
  baz : 3 // error because its not string
};

Playground Link

【讨论】:

  • 为什么是联合而不是交集?我什至不明白它如何与工会合作。谢谢。
  • @VincentJ a 和 b 的并集表示此类型是 a 或 b。但是交集意味着类型 c 是 a 和 b 的组合版本。所以它必须满足这两种类型的每一个约束。因此,如果我们在这里将 Foo 和 Bar 相交,我们将拥有 OP 的 Foo 版本,它试图让两个约束相互对抗。 (数字和字符串索引的字符串属性的长度属性类型)
  • 如果我用一个交叉点写它,它会给出与你的版本相同的结果(= 只有在 baz:3 上出现错误)。
  • @VincentJ 检查this。由于进行检查的顺序,它给出了相同的结果。如果您删除 baz 属性,它应该是有效的,但您会在问题中看到相同的错误。
【解决方案2】:

看看这个sn-p,它很好地解释了这一点

interface ArrStr {
  [key: string]: string | number; // Must accommodate all members

  [index: number]: string; // Can be a subset of string indexer

  // Just an example member
  length: number;
}

您可以查看这篇文章了解更多详细信息(我从那里选择了 sn-p)

https://basarat.gitbook.io/typescript/type-system/index-signatures

对于这个元素

同时拥有字符串和数字索引器
这不是一个常见的用例, 但是 TypeScript 编译器仍然支持它。然而,它具有 字符串索引器比数字更严格的限制 索引器。这是故意的,例如允许输入如下内容:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-13
    • 1970-01-01
    • 2018-12-18
    • 2019-02-06
    • 1970-01-01
    • 2023-03-15
    • 2021-11-19
    • 2020-11-21
    相关资源
    最近更新 更多