是否有一种类型安全的方法可以将较大的对象 reduce() 为打字稿中的新类型?

Is there a type-safe way to reduce() a larger object into a new type in typescript?

我有一个表示数据库查询结果的数据结构,它是一个具有许多属性的对象,所有属性都是标量(在我的例子中,都是字符串或数字)。我想提取这些属性的一部分并填充一个具有定义形状的新对象。

const input: Record<string, string | number> = { name: 'Jane', age: 42, fav_pet: 'Dog', fav_col: 'Blue', fav_dest: 'Paris' };
const FAVS = ['pet', 'col', 'dest'] as const;
type FavsType = {
  pet: string;
  col: string;
  dest: string;
}

const output: FavsType = FAVS.reduce((acc, key) => ({ ...acc, [key]: input['fav' + key] }), {});
//    ~~~~~~
//    ^^^^^^ Type '{}' is missing the following properties from type 'FavsType': pet, col, dest

问题是,如果我使用 reduce 方法执行此操作,Typescript 无法确定 reduce 的 return 值必须包含正确形状的对象。我也尝试过使用 Object.fromEntries(FAVS.map()) 得到类似的结果。

是否有任何不涉及显式分配每个 属性 的类型安全解决方案?

Playground Link

打字稿。当 Typescript 遇到 reduce 时,它​​必须声明它必须键入的新变量。

const output: FavsType = FAVS.reduce((acc, key) => ({
  ...acc,

  [key]: input[`fav${key}`],
}), ------> {} <------);

累加器被初始化为 {} 然后打字稿推断类型 '{}'.

从打字稿的角度来看,改变累加器不会改变它的类型。

你必须告诉打字稿

Trust me, the returned type is of FavsType

这就是断言的用武之地:

const output: FavsType = FAVS.reduce((acc, key) => ({
  ...acc,

  [key]: input[`fav${key}`],
}), {}) as FavsType;

理想情况下,typescript 应该看到对象的变化并推断出正确的 reduce 返回类型,但它还不是那么“聪明”。