【发布时间】:2020-10-14 12:39:55
【问题描述】:
我有一个表示数据库查询结果的数据结构,它是一个具有许多属性的对象,都是标量(在我的例子中,都是字符串或数字)。我想提取这些属性的一部分并填写一个具有定义形状的新对象。
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 的返回值必须包含正确形状的对象。我也尝试过使用 Object.fromEntries(FAVS.map()) 得到类似的结果。
是否有任何类型安全的解决方案不涉及显式分配每个属性?
【问题讨论】:
-
reduce 的返回类型是从第二个参数推断出来的(在本例中为
{})或由 generic type 提供(例如.reduce<FavsType>(...))。 -
你可以使用类型断言
const output: FavsType = FAVS.reduce((acc, key) => ({ ...acc, [key]: input['fav' + key] }), <FavsType>{}); -
您也可以使用 keyof 操作使
const FAVS类型安全,因为该数组仅包含FavsTypeconst FAVS: (keyof FavsType)[] = ['pet', 'col', 'dest']的键的值 -
@IAMTHEBEST 实际上产生比
as const更弱的类型,因为它允许突变。 -
@IAMTHEBEST 我以另一种方式查看关系 - 它是
FavsType包含来自FAVS的所有条目。所以,对我来说,从另一个方向派生为映射类型似乎更合乎逻辑:type FavsType = { [key in typeof FAVS[number]]: string; }
标签: typescript types reduce