Typescript:从对象数组派生联合类型

问题描述 投票:8回答:2

我想声明一个类型强制的项数组,并能够从中派生联合类型。如果您未为数组中的项目显式指定类型,则此模式有效。我不确定如何最好地解释它,所以这里有一个例子:

示例1

type Pair = {
  key: string;
  value: number;
};

const pairs: ReadonlyArray<Pair> = [
  { key: 'foo', value: 1 },
  { key: 'bar', value: 2 },
] as const;

type Keys = typeof pairs[number]['key']

示例2

type Data = {
  name: string;
  age: number;
};

const DataRecord: Record<string, Data> = {
  foo: { name: 'Mark', age: 35 },
  bar: { name: 'Jeff', age: 56 },
} as const;

type Keys = keyof typeof DataRecord;

这里是使用as const时导出密钥的示例。我想要相同的行为,但要显式键入数组。

const pairs = [
  { key: 'foo', value: 1 },
  { key: 'bar', value: 2 },
] as const;

type Keys = typeof pairs[number]['key']; // "foo" | "bar"

键的期望值:"foo"|"bar"

键的实际值:string

javascript typescript const typeof keyof
2个回答
3
投票

对于变量,您可以让编译器从初始化中推断类型,也可以明确地将其写出。如果像您一样显式地编写它,则将根据注释检查初始化值,但是初始化器的实际类型不会影响变量的类型(因此会丢失所需的类型信息)。如果让编译器进行推断,就不再可能限制类型以符合特定接口(如您所愿)]

解决方案是使用泛型函数来约束值并推断其实际类型:

type Pair = {
  key: string;
  value: number;
};
function craetePairsArray<T extends readonly Pair[] & Array<{key: V}>, V extends string>(...args: T) {
    return args
}

const pairs = craetePairsArray(
  { key: 'foo', value: 1 },
  { key: 'bar', value: 2 },
)

type Keys1 = typeof pairs[number]['key']

type Data = {
  name: string;
  age: number;
};

function craeteDataObject<T extends Record<string, Data>>(arg: T) {
    return arg;
}
const DataRecord = craeteDataObject({
  foo: { name: 'Mark', age: 35 },
  bar: { name: 'Jeff', age: 56 },
})

type Keys2 = keyof typeof DataRecord;

Playground Link

注意:对于数组的情况,我们需要让编译器更有力地为key推断字符串文字类型,从而推断整个& Array<{key: V}>,其中V是扩展string的类型参数>


2
投票

通常的方法是:

© www.soinside.com 2019 - 2024. All rights reserved.