如何为条件返回函数或数值的TypeScript函数添加类型定义
问题描述
我正在优化代码库,试图减少其中的any类型。遇到一个逻辑类似GSAP mapRange()的函数,它会根据传入的value条件返回函数执行结果或函数本身,难以确定其最佳TypeScript类型标注方式,甚至不确定是否该保留原有结构。
原有代码如下:
const conditionalReturn = (value?: number, func?: any) => value || value === 0 ? func(value) : func
const mapRange = (inMin:number, inMax: number, outMin: number, outMax: number, value?: number) => { const inRange = inMax - inMin; const outRange = outMax - outMin; return conditionalReturn(value, (value: any) => outMin + ((((value - inMin) / inRange) * outRange) || 0)); } export const mapLengthToWidth = (inMin: number, inOut: number, outMin: number, outMax: number) => { const mapFn = mapRange(inMin, inOut, outMin, outMax); return (text: string): number => mapFn(text.length); }; const conditionalReturn = (value?: number, func?: any) => value || value === 0 ? func(value) : func
我尝试过type sampleReturn = (value?: number) => number || ((x: number | string) => number)这样的基础类型定义,但无法实现仅在未传入value时返回函数的逻辑。我的简化实现代码如下:
export const mapRange = ( inMin: number, inMax: number, outMin: number, outMax: number, value?: number | string ) => { const inRange = inMax - inMin; const outRange = outMax - outMin; const mapRangeFunc = (value: number) => { return outMin + (((value - inMin) / inRange) * outRange || 0); }; const valueAsInt = Number(value); if (value == undefined || Number.isNaN(valueAsInt)) return mapRangeFunc; return mapRangeFunc(valueAsInt); }; export const mapLengthToWidth = ( inMin: number, inOut: number, outMin: number, outMax: number ) => { const mapFn = mapRange(inMin, inOut, outMin, outMax); if (typeof mapFn !== 'function') return; return (text: string): number => mapFn(text.length); };
请求正确的TypeScript类型标注方案。
解决方案
要实现这种根据参数是否存在返回不同类型的逻辑,TypeScript的函数重载是最直观清晰的方案,能精准匹配不同调用场景的返回值类型。
1. 给mapRange添加重载类型
为mapRange定义两个重载签名,分别对应传入value和不传入value的场景:
// 重载签名1:传入value,直接返回计算后的数值 export function mapRange( inMin: number, inMax: number, outMin: number, outMax: number, value: number | string ): number; // 重载签名2:不传入value,返回用于后续映射的函数 export function mapRange( inMin: number, inMax: number, outMin: number, outMax: number ): (value: number) => number; // 函数实现体 export function mapRange( inMin: number, inMax: number, outMin: number, outMax: number, value?: number | string ) { const inRange = inMax - inMin; const outRange = outMax - outMin; const mapRangeFunc = (numValue: number): number => { return outMin + (((numValue - inMin) / inRange) * outRange || 0); }; const valueAsInt = Number(value); if (value == undefined || Number.isNaN(valueAsInt)) { return mapRangeFunc; } return mapRangeFunc(valueAsInt); }
2. 优化mapLengthToWidth的类型
此时TypeScript能正确推断出mapRange在不传入value时返回函数类型,因此可以去掉多余的类型判断,简化代码:
export const mapLengthToWidth = ( inMin: number, inOut: number, outMin: number, outMax: number ) => { const mapFn = mapRange(inMin, inOut, outMin, outMax); return (text: string): number => mapFn(text.length); };
3. 原conditionalReturn函数的类型优化(可选)
如果需要保留这个工具函数,同样可以用重载给它加上明确类型:
// 重载签名1:传入value,返回函数执行结果 function conditionalReturn<T>(value: number, func: (val: number) => T): T; // 重载签名2:不传入value,返回函数本身 function conditionalReturn<T>(value?: undefined, func: (val: number) => T): (val: number) => T; // 函数实现体 function conditionalReturn<T>(value?: number, func?: (val: number) => T) { if (value === undefined) { return func!; } return func!(value); }
以上方案完全消除了any类型,TypeScript可以在不同调用场景下精准推断返回值类型,避免类型歧义。
内容的提问来源于stack exchange,提问作者asd
相关产品推荐
相关产品推荐

