将对象键限制为枚举值,同时不要求所有键都存在并且对象值不被视为未定义

sim*_*Pod 4 enums typescript

这里有很多类似的问题,但它们没有涵盖帖子末尾的清单(特别是“值未定义”部分)。

我有一个枚举

enum E {
  A = 'A',
  B = 'B'
}
Run Code Online (Sandbox Code Playgroud)

然后我想将我的对象值限制为状态,{ [key in E]: string }但这要求我实例化该对象已经是所有枚举的键。这是不允许的:

const state: { [key in E]: string } = {};
Run Code Online (Sandbox Code Playgroud)

类型“{}”缺少类型“{ A: string;”的以下属性 B:字符串;}':A、B

所以我尝试这样约束它{ [key in E]?: string }。这允许我省略枚举键,从而允许实例化空对象{}并检查键值是否在枚举范围内:

state.A = 'x'; // ok
state.C = 'y'; // gives error which is nice
Run Code Online (Sandbox Code Playgroud)

但后来我在 forEaching 对象条目时遇到了问题

Object.entries(state).forEach(([key, value]) => console.log(value === undefined));
Run Code Online (Sandbox Code Playgroud)

Typescript 认为这value可以是类型string|undefined,但事实并非如此。

仅使用字符串作为键时,该值不被视为未定义

const state: { [key: string]: string } = {};
Run Code Online (Sandbox Code Playgroud)

游乐场示例


如何将对象键限制为枚举值,同时不需要它们的存在并且值不是未定义的?

清单:

state.A = 'x' // ok
state.C = 'x' // error
Object.entries(state).forEach(([key, value])=>console.log(value.charAt(0))); // ok, no Object is possibly 'undefined'.(2532) error
Run Code Online (Sandbox Code Playgroud)

TLDR:我想去掉assert示例中

Lin*_*ste 6

就打字稿而言,从对象中省略与显式设置A为 相同。这样做很好:Aundefined

const state: { [key in E]?: string } = {};
state.A = undefined;
Run Code Online (Sandbox Code Playgroud)

@captain-yossarian 为您提供了一种很好但非常复杂的方法来防止这种行为。更简单的方法是简单地过滤掉任何undefined值。

这个回调是一个类型保护,它确保元value组中的[key, value]被定义。

const isDefinedValue = <T,>(tuple: [string, T | undefined]): tuple is [string, Exclude<T, undefined>] => {
  return tuple[1] !== undefined;
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以Object.entries在使用之前过滤它。

Object.entries(state)
  .filter(isDefinedValue)
  .forEach(([key, value])=>console.log(value.charAt(0)));  // value is `string`
Run Code Online (Sandbox Code Playgroud)