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

醉酒当歌 提交于 2020-12-12 05:33:52

问题


I have a data structure that represents the results from a database query, which is an object with many properties, all scalars (in my case, all either strings or numbers). I want to extract a portion of these properties and fill out a new object that has a defined shape.

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

The problem is, if I use the reduce method to do this, Typescript is unable to figure out that the return value of the reduce must contain an object in the correct shape. I've also tried using Object.fromEntries(FAVS.map()) with similar results.

Is there any type-safe solution to this which doesn't involve assigning each property explicitly?

Playground Link


回答1:


Be Typescript. When Typescript encounter the reduce, it have to declare new variables that it have to type.

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

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

The accumulator being initialized as {} then typescript infer the type '{}'.

Mutating the accumulator won't change it's type from typescript point of view.

You will have to tell typescript

Trust me, the returned type is of FavsType

That's where assertions comes in :

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

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

Ideally typescript should see the mutation of the object and infer the proper reduce returned type, but it ain't that "smart" yet.



来源:https://stackoverflow.com/questions/62551919/is-there-a-type-safe-way-to-reduce-a-larger-object-into-a-new-type-in-typescri

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!