TypeScript中能否复用函数参数定义?求可行实现方案
答案
当然可以!现在TypeScript已经完全支持复用函数参数定义的需求了,而且有几种简洁的实现方式,正好匹配你想要的场景:
方法1:直接定义可复用的参数元组
这是最直观的方式,把你想要复用的参数结构定义成一个元组类型,然后在需要的地方直接引用:
import { EventEmitter } from 'events'; // 定义要复用的事件参数元组,明确标注每个参数的名称和类型 type FooEventArgs = [x: string, y: number]; class MyEmitter extends EventEmitter { // 在emit中使用元组 emit(event: "foo", ...args: FooEventArgs): boolean; // 保留EventEmitter原有的通用签名 emit(event: string | symbol, ...args: any[]): boolean { return super.emit(event, ...args); } // 在on的回调中复用同一个元组 on(event: "foo", listener: (...args: FooEventArgs) => void): this; // 保留通用签名 on(event: string | symbol, listener: (...args: any[]) => void): this { return super.on(event, listener); } }
这种方式的好处是结构清晰,一眼就能看出参数的定义,而且完全支持任意数量的参数,解决了你提到的早期方案只能支持0或1个参数的问题。
方法2:从已有函数签名中提取参数(内置工具类型)
如果你已经有了某个函数的定义(比如先写了emit,想复用它的参数到on里),可以用TypeScript内置的Parameters工具类型来提取参数类型,甚至可以进一步筛选出你需要的部分:
import { EventEmitter } from 'events'; class MyEmitter extends EventEmitter { // 先定义emit的特定签名 emit(event: "foo", x: string, y: number): boolean; emit(event: string | symbol, ...args: any[]): boolean { return super.emit(event, ...args); } // 提取emit("foo")的参数,排除第一个event参数 type FooEventArgs = Parameters<typeof MyEmitter["emit"]> extends [string, ...infer Args] ? Args : never; // 在on中复用提取出的参数 on(event: "foo", listener: (...args: FooEventArgs) => void): this; on(event: string | symbol, listener: (...args: any[]) => void): this { return super.on(event, listener); } }
这里Parameters<typeof MyEmitter["emit"]>会提取emit函数的所有参数类型组成的元组,我们再通过条件类型infer把第一个event参数排除,只保留后面的业务参数。
关于你提到的TS议题
你关注的那些早期议题确实推动了TypeScript类型系统的完善,现在TypeScript 3.1及以上版本已经内置了Parameters、ReturnType等工具类型,完全覆盖了你想要的参数复用场景,不需要依赖复杂的自定义类型操作了。
内容的提问来源于stack exchange,提问作者Coderer
相关产品推荐
相关产品推荐

