TypeScript一元函数类型标注 内置泛型与可选泛型参数实现方案
内置泛型相关问题
TypeScript 标准库没有提供专门针对「接收单个对象参数的一元函数」的内置泛型类型。
现有内置类型里,通用Function类型过于宽泛,几乎没有类型约束能力,官方本身就不推荐使用;Parameters、ReturnType等工具类型是用来从已有函数类型中提取参数、返回值的,不是用来在定义函数时约束形状的,和你的使用场景不匹配。
自定义泛型的合理性
自己封装FN这类泛型是完全合理、且在TS项目中非常普遍的工程实践。
你提到的React内置FC本质上也是框架层针对自身组件场景封装的专用函数类型,TS标准库不可能覆盖所有工程场景下的高频类型封装需求。你设计的这个类型边界非常清晰:专门约束接收单个对象参数、实现命名参数风格的一元函数,既可以减少重复写函数类型的冗余代码,也能统一团队的函数定义风格,没有任何问题,只要注意不要把它滥用在多参数、无参数的函数场景下即可。
扩展问题:返回值自动推断的实现方案
首先要明确TS的类型优先级规则:如果给变量显式写了固定的类型标注,TS会以标注的类型为准,右侧的赋值内容只会做类型兼容性检查,不会反向给标注里的泛型参数做推断。所以严格保持const 变量名: FN<Args> = 函数实现的写法,是没法直接让TS自动推导返回值、把变量类型窄化为对应返回值的函数类型的。
不过可以根据你的TS版本和使用习惯,选择以下两种类型安全的方案实现需求:
- 方案1:使用
satisfies运算符(TS 4.9及以上版本推荐,写法最简洁)
不需要给返回值设置泛型参数,借助satisfies做入参约束,同时保留对实现侧的类型推断:
这个写法的效果:// 只约束入参形状,不固定返回值 type UnaryObjFn<TArgs extends object> = (args: TArgs) => unknown; const calcTotalWeight = (({ itemWeight, quantity }) => itemWeight * quantity) satisfies UnaryObjFn<Args>;- 会强制检查函数入参必须符合
Args的结构,入参字段名、类型写错会直接报类型错误 - 不会固定返回值类型,变量的类型完全根据函数实现自动推断
- 最终
typeof calcTotalWeight的结果就是(args: Args) => number,完全符合预期
- 会强制检查函数入参必须符合
- 方案2:使用泛型辅助函数(兼容TS 4.9以下版本)
写一个零运行时开销的辅助函数,利用泛型推断自动推导返回值:
这个写法最终推导出来的函数类型和方案1完全一致,入参有约束,返回值自动推断,不需要手动标注返回值类型。const defineUnaryFn = <TArgs extends object>() => { return <TReturn>(fn: (args: TArgs) => TReturn) => fn; }; // 使用时先传入参数类型,再写函数实现,入参会自动获得类型提示 const calcTotalWeight = defineUnaryFn<Args>()(({ itemWeight, quantity }) => itemWeight * quantity);
不推荐给第二个泛型参数设置
any作为默认值的写法,这种写法会让返回值类型丢失类型安全,变成any类型,违背了TS类型标注的初衷。
内容的提问来源于stack exchange,提问作者thecartesianman
相关产品推荐
相关产品推荐

