TypeScript中如何分离泛型函数的类型定义与实现
问题原因
你遇到报错的核心是搞混了「泛型类型」和「泛型函数类型」的定义位置:
你写的type MyFuncType<T> = () => void把泛型参数放在了type的声明位,这表示MyFuncType本身是一个需要传入类型参数才能生成具体类型的泛型类型,你直接写MyFuncType不传参数,TS自然会抛错要求你补全类型实参。这种写法定义出来的类型,本质是「先传T,再得到对应的函数类型」,而不是「这个函数本身支持泛型」。
正确写法
如果要定义本身带泛型参数的函数类型(即调用函数时才指定泛型具体类型,而非声明函数实现时就固定T),把泛型参数<T>挪到函数签名的位置即可:
// 泛型参数定义在函数签名上,这才是泛型函数的类型 type MyFuncType = <T>() => void // 此时标注类型不需要额外传泛型参数,直接写MyFuncType即可 const myFuncImp: MyFuncType = <T>() => { // 函数实现内可以正常使用T类型 } // 调用函数时再指定不同的T类型即可 myFuncImp<string>() myFuncImp<number>()
两种泛型位置的差异
别搞混两种写法的适用场景:
- 泛型写在type上:
type MyFuncType<T> = () => T,属于泛型类型,声明函数实现时就要固定T的类型。比如const strFunc: MyFuncType<string> = () => 'hello',这个函数调用后返回值永远是string,泛型在声明阶段就确定了。 - 泛型写在函数签名上:
type MyFuncType = <T>() => T,属于泛型函数类型,声明实现时不需要固定T,每次调用都可以传入不同的类型参数,函数逻辑是通用的。
带约束的泛型写法
如果要给泛型加类型约束,直接在函数签名的泛型位添加即可,比如要求T必须是有id属性的对象:
type MyFuncType = <T extends { id: string }>(arg: T) => void const myFuncImp: MyFuncType = <T extends { id: string }>(arg: T) => { console.log(arg.id) }
内容的提问来源于stack exchange,提问作者Corno
相关产品推荐
相关产品推荐

