首页 > 解决方案 > 指定值的类型而不指定对象的键类型

问题描述

我有一个相当复杂interface的情况,其中有许多众所周知的实例。这些实例应该可以通过某种 ID 引用。理想情况下,我想在一个对象中定义所有这些众所周知的实例,以便我可以使用keyof运算符轻松地为键设置一个类型。

interface Complex { 
  frobs: number[];
  type: 'A' | 'B';
} // More complicated in reality

const COMMON = {
  foo: { type: 'A', frobs: [] },           // this is fine
  bar: { type: 'B', frobs: [1], zorg: 1 }, // unwanted extra
  baz: { type: 'A', noFrobs: "uh-oh" },    // frobs missing
}

Type CommonId = keyof typeof COMMON; // Great, valid Ids are "foo" | "bar" | "baz"

但是如果我指定没有任何类型的对象(如上所述),Typescript 当然不会强制该对象中的所有值都应该是相同的类型。

所以我想指定所有值都必须是类型Complex,但如果不指定键类型,我就无法这样做。现在我必须两次提到每个键:一次作为对象的一部分,CommonId一次在对象中:

interface Complex { 
  frobs: number[]; 
  type: 'A' | 'B';
} // More complicated in reality
type CommonId = "foo" | "bar";         // Much more common objects in reality

const COMMON: { 
  [commonId in CommonId]: Complex 
} = {
  foo: { type: 'A', frobs: [] },
  bar: { type: 'B', frobs: [1] }
}

有没有办法两全其美?我很想COMMON用一个新的键值对来扩展变量,以自动将该键添加到CommonId类型中。

标签: typescript

解决方案


您可以首先创建一个不键入的变量,使用它来获取键类型,然后导出相同的值但具有类型:

interface Complex { frobs: number[]; }

const _common = {
  foo: { frobs: [] },
  bar: { frobs: [1] }
};

type CommonId = keyof typeof _common;

export const COMMON: { 
  [commonId in CommonId]: Complex 
} = _common;

游乐场链接


推荐阅读