具有可选键但在 TypeScript 中具有强制值的对象

时间:2021-06-04 16:06:55

标签: typescript

我想要一个地图类型,在 Typescript 中有一个记录,键 是一个枚举。

我有这个枚举:

enum CatName {
  miffy = "miffy",
  boris = "boris",
  mordred = "mordred",
}

还有这个界面:

interface CatInfo {
  age: number;
  breed: string;
}

如果我使用这种类型:

type Cats = Record<CatName, CatInfo>

我必须使用枚举的所有键,这不是我想要的。

如果我使用这种类型:

type Cats = Partial<Record<CatName, CatInfo>>

我可以根据需要仅使用 Enum 的某些键创建映射,但 CatInfo 现在可能未定义,我需要它是强制性的。

有没有办法实现带有一些键但带有强制值的映射?

如果有帮助,这里有一个 link 到游乐场。

1 个答案:

答案 0 :(得分:0)

对于 4.3 及以下版本的 TypeScript,没有直接的方法可以做到这一点。 Optional properties 允许缺失,但也允许存在-但是-undefined。从某人只是读取这种财产的价值的角度来看,没有区别;但是从向这样的属性写入值或通过 inhasOwnProperty() 检查是否存在的角度来看,是有区别的。问题 microsoft/TypeScript#13195 要求 TypeScript 区分缺失和未定义。对于此类版本的 TypeScript,正确的做法可能是接受 undefined。如果要检查属性是否存在且已定义,则不应使用 inhasOwnProperty():

if ("boris" in cats2) {
  cats2.boris.age.toFixed(2); // error in TS4.3-
//~~~~~~~~~~~
// Object is possibly 'undefined'.
}

if (cats2.boris !== undefined) {
  cats2.boris.age.toFixed(2); // okay in TS4.3-
}

相反,您应该使用键索引对象并确保值不是 undefined

if (cats2.boris !== undefined) {
  cats2.boris.age.toFixed(2); // okay in TS4.3-
}

Playground link to code


对于 TypeScript 4.4 及更高版本,如果启用它,将会有一个新的编译器选项来修复 microsoft/TypeScript#13195。有关详细信息,请参阅 microsoft/TypeScript#43947。 (更新 2021-06-10:此功能最初将通过新的 --strictOptionalProperties 编译器标志启用,该标志将包含在 --strict suite of compiler options 中。但是,根据 this comment,该标志将被重命名并从 --strict 中删除,因此任何想要在 TypeScript 4.4 及更高版本中看到此行为的人都需要通过一些尚未确定名称的编译器标志手动启用它。)

如果您使用此功能,您将不再被允许将 undefined 分配给可选属性(除非该属性的类型明确包含 undefined),同时您仍需要检查您阅读的属性undefined

const cats2: Cats = {
  miffy: { age: 10, breed: "Persian" },
  boris: undefined, // error in TS4.4+!
  // Type 'undefined' is not assignable to type 'CatInfo'
};

并且您还可以使用 inhasOwnProperty() 检查密钥是否存在,并在阅读时消除 undefined 的可能性:

if ("boris" in cats2) {
  cats2.boris.age.toFixed(2); // okay in TS4.4+
}

Playground link to code

相关问题