【问题标题】:Why can't this index signature be optional?为什么这个索引签名不能是可选的?
【发布时间】:2019-08-03 20:41:18
【问题描述】:

在 TypeScript 中,有一个名为 Partial<T> 的预定义类型。它是这样定义的:

type Partial<T> = {
  [P in keyof T]?: T[P];
}

显然,索引签名被标记为可选,这是可行的。如果我尝试做同样的事情:

interface IDictionary<T> {
  [ key: string ]?: T
}

TypeScript 抱怨 ?。这是因为接口可能不包含可选字段,还是这是什么原因?

【问题讨论】:

  • Partial 定义是一个映射类型,它说:“遍历所有成员并添加可选修饰符”。你想通过将索引签名标记为可选来实现什么?
  • Mapped typesindex signatures 看起来相似但并不相同。索引签名不能标记为可选,实际上总是被视为可选(在某种意义上,您不需要在匹配对象中拥有所有可能的索引键);没有办法说“必需”。我同意语法令人困惑并且可能具有误导性,但事实就是如此。

标签: javascript typescript


【解决方案1】:

不,打字稿接口允许可选字段。原因是它没有意义,逻辑上

Partial&lt;T&gt; 正在为密钥的外观添加一个约束 => P in keyof T。 如果您在此处删除?,则意味着Partial&lt;T&gt;T 相同。

interface Car {
  brand: string;
  color: string;
}

// this is exactly the same as the interface declaration below
type PartialCar = Partial<Car>;

// this is exactly the same as the type above
interface PartialCar = { 
  brand?: string;
  color?: string;
}

const carWithoutColor: PartialCar = { brand: "BMW" }
const thisIsStillAPartialCar: PartialCar = {}

对于您的IDictionary&lt;T&gt;,情况有所不同。您没有在键上添加约束(只是说它是 any string)。所以说它可以是可选的是没有意义的,因为它无论如何都是可选的(就它而言可能是anystring)。
在您的 IDictionary&lt;T&gt; 中,您只是在值部分添加了一个约束,该约束需要是 T 的类型。

const numberDictionary: IDictionary<number> = { someStupidKey: 1, oneMoreKey: 2 }
const stringDictionary: IDictionary<string> = { someStupidKeyAWFSAFWAFW: "foo", oneMoreKey: "bar" }

// typescript will assume that "someVariable" is a number
const someVariable = numberDictionary.thisIsUndefined;

// which is why this will not end up in a compile error but a runtime error
const someResult =  1 + someVariable;

正如您所看到的,每个键都已经可选了,您声明了IDictionary&lt;T&gt;

【讨论】:

  • 这听起来是对的,但它仍然留下了一个问题,为什么[P in keyof T] 表示 T 的 所有 键,而 [P in string] 仅表示 一些 (any) 字符串。没有有限数量的键可以满足约束“所有字符串”这一事实并不能证明 imo 的模棱两可。
  • 我认为说索引签名密钥是可选的是冗余(并且不受支持),而不是说它“没有意义”。这当然是有道理的,并且在 TS 中允许使用一些冗余结构(例如,{a?: string}{a?: string | undefined} 都被允许并且意思相同;{[K in keyof T]?: T[K]}{[K in keyof T]+?: T[K]} 都被允许并且意思相同)跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
相关资源
最近更新 更多