TypeScript强类型工具中ReturnType<T>异常问题排查与优化
实现自动保留窄类型的
ifArray工具函数 我实现了一个ifArray工具函数,功能是接收一个输入值和两个回调函数,分别处理输入为数组和非数组的情况,核心目标是尽可能保留输入的窄类型。
初始代码
export type Narrowable = string | number | boolean | symbol | object | undefined | void | null | {}; export type IsArray<T> = [T] extends [any[]] ? true : [T] extends [readonly any[]] ? true : false; export type IfArray<T, IF, ELSE> = IsArray<T> extends true ? IF : ELSE; export function isArray<T>(i: T) { return (Array.isArray(i) === true) as IsArray<T>; } export function ifArray< T extends Narrowable, IF extends <N extends T & readonly any[]>(arr: N) => any, ELSE extends <N extends Exclude<T, any[]>>(nonArr: N) => any >(val: T, isAnArray: IF, isNotAnArray: ELSE) { return ( isArray(val) ? isAnArray(val as any) : isNotAnArray(val as any) ) as IfArray< T, ReturnType<IF>, ReturnType<ELSE> // 此处类型推导异常,返回any >; }
测试用例
我编写了4个测试用例验证类型推导结果:
const whatAmI0 = ifArray( "developer" as string, i => `You are a problem child with ${i.length} personalities` as const, i => `You are a ${i}` as const ); const whatAmI1 = ifArray( "developer", i => `You are a problem child with ${i.length} personalities` as const, i => `You are a ${i}` as const ); const whatAmI2 = ifArray( ["developer", "person", "husband"], i => `You are a problem child with ${i.length} personalities` as const, i => `You are a ${i}` as const ); const whatAmI3 = ifArray( ["developer", "person", "husband"] as const, i => `You are a problem child with ${i.length} personalities` as const, i => `You are a ${i}` as const );
其中whatAmI1的类型推导失败,ReturnType<ELSE>返回any类型。
已完成的修复
通过修改ELSE的泛型约束,移除其内部泛型、直接指定参数类型,修复了whatAmI1的类型推导问题:
export function ifArray< T extends Narrowable, IF extends <N extends T & readonly any[]>(arr: N) => any, // 修改:移除ELSE的泛型,直接指定参数类型 ELSE extends (nonArr: Exclude<T, any[]>) => any >(val: T, isAnArray: IF, isNotAnArray: ELSE) { return ( isArray(val) ? isAnArray(val as any) : isNotAnArray(val as any) ) as IfArray< T, ReturnType<IF>, ReturnType<ELSE> >; }
当前需求
目前仍需手动为回调函数的返回值添加as const才能保留窄类型,希望实现无需手动添加as const,即可自动保留回调返回值的窄类型。
内容的提问来源于stack exchange,提问作者ken
相关产品推荐
相关产品推荐

