映射 Typescript 泛型数组

Map Typescript generic array

假设我有一个带有一组静态键的对象,然后是一个将这些键的子集指定为静态数组的类型:

const myBigStaticObject = {
  key1: () => 'foo',
  key2: () => 'bar',
  // ...
  keyN: () => 'fooN',
}

type BigObject = typeof myBigStaticObject

type Keys = ['key2', 'keyN']

有没有一种很好的方法可以以编程方式创建一个映射类型,该映射类型将 Keys 作为其通用参数,即执行以下操作:

type ObjectValueFromKeys<K extends (keyof BigObject)[]> = // ???

// such that:

ObjectValueFromKeys<Keys> = [() => 'bar', () => 'fooN']

这里对象的等价物是:

const objectKeys = {
  a1: 'key2';
  a2: 'keyN';
}

type ObjectValueFromObjectKeys<M extends Record<string, keyof BigObject>> = {
  [K in keyof M]: BigObject[M[K]]
}

// then

type ObjectValueFromObjectKeys<typeof objectKeys> = {
  a1: () => 'bar';
  a2: () => 'fooN';
}

您可能不知道这一点,但您实际上可以将映射类型与数组和元组一起使用,同时在输出中仍保留 array/tuple 类型!

这意味着你可以使用这样的东西,它首先检查值是否是大对象的键:

type ObjectValueFromKeys<K extends (keyof BigObject)[]> = {
    [P in keyof K]: K[P] extends keyof BigObject ? BigObject[K[P]] : K[P];
};

它就像一个魅力:

type T1 = ObjectValueFromKeys<["key2", "keyN"]>;
//   ^? [() => "bar", () => "fooN"]

不相信我? See for yourself.

你可能会注意到大对象中使用了as const

    key1: () => 'foo' as const,

这是因为,出于某种原因,TypeScript 无法推断出此函数只能return"foo"。因此,我使用 as const 使其 return 成为我们案例的文字 "foo",以便我们可以查看解决方案是否有效。