TypeScript如何依据入参是否为undefined动态设置泛型函数返回类型
你的实现失效的核心原因是TypeScript无法自动根据valueKey是否传入来缩小泛型的条件返回类型,默认会返回两种类型的联合,因此出现赋值报错。
采用函数重载可以完美匹配你的预期需求,实现代码如下:
export interface ToObject<T> { [k: string]: T; } // 重载1:未传入valueKey时,返回值为对象映射,值类型为原数组项类型 export function toObject<T>(list: T[], key: keyof T): ToObject<T>; // 重载2:传入valueKey时,返回值为对象映射,值类型为对应valueKey的属性类型 export function toObject<T, V extends keyof T>(list: T[], key: keyof T, valueKey: V): ToObject<T[V]>; // 函数实现 export function toObject<T, V extends keyof T>(list: T[], key: keyof T, valueKey?: V) { return valueKey === undefined ? list.reduce((all, cur) => ({ ...all, [cur[key] as unknown as string]: cur }), {} as ToObject<T>) : list.reduce((all, cur) => ({ ...all, [cur[key] as unknown as string]: cur[valueKey] }), {} as ToObject<T[V]>); }
效果验证
interface Data{ a: string; b: string; c: string; } const list: Data[] = [ {a:'a', b: 'b', c: 'c'}, {a:'1', b: '2', c: '3'} ]; // 用法1 无报错,类型自动推导为ToObject<Data> const dataMap: ToObject<Data> = toObject(list, 'a'); // 用法2 无报错,类型自动推导为ToObject<string> const dataKeyMap: ToObject<string> = toObject(list, 'a', 'b');
函数重载的优势在于可以让TypeScript直接根据入参的数量、类型匹配对应的返回类型规则,不需要依赖条件类型的自动推导,避免了泛型默认值带来的联合类型歧义问题。
内容的提问来源于stack exchange,提问作者Joy Biswas
相关产品推荐
相关产品推荐

