为什么 Typescript 在使用 [key in enum] 索引签名时不将枚举成员识别为有效属性

Why Does Typescript not Recognize Enum Members as Valid Properties When Using [key in enum] Index Signature

我正在处理一个 TypeScript 项目,在使用枚举成员作为接口的索引键时,我 运行 遇到了一个奇怪的问题。我的枚举和接口都在全局 .d.ts 文件中声明(没有导入或导出)。

// enums.d.ts
...
enum ItemFlag {
  IsPushable = "isPushable",
  IsTakable = "isTakable",
  IsUnique = "isUnique"
}
...

// interfaces.d.ts
...
interface IThingProps {
  id: string;
  name: string;
}

interface IItemProps extends IThingProps {
  [key in ItemFlag]?: boolean;
}
...

但是,当我尝试创建一个实现 IItemProps 接口的对象时:

const props: IItemProps = {
  id: "item_small_cup",
  name: "small cup",
  [ItemFlag.IsTakable]: true
};

我收到以下错误:

“类型‘{ id: string; name: string; isTakable: boolean; }’不可分配给类型 'IItemProps'。 对象字面量只能指定已知属性,并且类型 'IItemProps' 中不存在“[ItemFlag.IsTakable]”。

奇怪的是我用另一个枚举来做这件事而且它工作正常。唯一的区别是我使用它内联声明对象的类型,如:

const genders: {[key in Gender]: Pronouns; } = {
  [Gender.It]: {
    they: "it",
    them: "it",
    // You get the idea
  }
}

我想这个例子也没有 属性 作为可选,但是删除了可选的 '?' ItemFlag 的索引签名根本不会改变错误。

对这种奇怪的、前后矛盾的行为有什么看法吗?

尝试使用类型而不是接口:


enum ItemFlag {
  IsPushable = "isPushable",
  IsTakable = "isTakable",
  IsUnique = "isUnique"
}

type IThingProps =  {
  id: string;
  name: string;
}

type IItemProps  = IThingProps & {
  [key in ItemFlag]?: boolean;
}

const props: IItemProps = {
  id: "item_small_cup",
  name: "small cup",
  [ItemFlag.IsTakable]: true
};

您要构建的是 Mapped Type 并且打字稿不支持映射接口。或者至少您将无法在接口上定义具体的 property/method。

根据一般经验,除非需要接口,否则我会使用类型。

这是一个有用的答案,它描述了两者之间的区别。