如何复用带泛型的TypeScript函数类型签名?
在TypeScript中复用带泛型的函数类型签名的最优语法
要复用带泛型的函数类型签名,最简洁的方式是定义泛型函数类型(或接口),然后让多个函数直接实现该类型,避免手动通过Parameters和ReturnType提取类型的冗余代码。
方案一:使用泛型函数类型别名
首先定义一个包含泛型的函数类型别名,直接描述函数的参数和返回值结构:
type CountFunction = <T extends object>(arg: T) => [T, number]; function log<T extends object>(arg: T) { console.log(arg); } // 直接复用CountFunction类型 const countWithKeys: CountFunction = (arg) => { const count = Object.keys(arg).length; log(arg); // TypeScript自动推断泛型T,无需手动指定 return [arg, count]; }; const countWithLoop: CountFunction = (arg) => { let count = 0; for (const i in arg) { count++; } log(arg); return [arg, count]; };
方案二:使用泛型函数接口
如果偏好接口风格,也可以用泛型函数接口实现同样的效果:
interface CountFunction { <T extends object>(arg: T): [T, number]; } function log<T extends object>(arg: T) { console.log(arg); } const countWithKeys: CountFunction = (arg) => { const count = Object.keys(arg).length; log(arg); return [arg, count]; }; const countWithLoop: CountFunction = (arg) => { let count = 0; for (const i in arg) { count++; } log(arg); return [arg, count]; };
为什么这比原写法更优
原写法中每次都通过Parameters<CountResult<T>>[0]和ReturnType<CountResult<T>>提取类型,代码冗余且可读性差。而上述方案直接将函数绑定到预定义的泛型函数类型上:
- 无需重复声明泛型参数
<T extends object>(类型会自动推断) - 参数和返回值类型自动继承,避免手动提取
- 函数实现时无需关心类型细节,只需要符合签名逻辑即可
保留function声明的替代方案
如果必须使用function关键字声明函数,可以直接复用泛型类型的返回值,同时简化参数定义:
type CountResult<T extends object> = (arg: T) => [T, number]; function log<T extends object>(arg: T) { console.log(arg); } function countWithKeys<T extends object>(arg: T): ReturnType<CountResult<T>> { const count = Object.keys(arg).length; log(arg); return [arg, count]; } function countWithLoop<T extends object>(arg: T): ReturnType<CountResult<T>> { let count = 0; for (const i in arg) { count++; } log(arg); return [arg, count]; }
这种写法比原写法略简洁(参数直接用T而非Parameters提取),但仍不如前两种方案高效。
内容的提问来源于stack exchange,提问作者Quang Van
相关产品推荐
相关产品推荐

