如何阻止TypeScript接受签名相同但类型不同的函数作为参数
解决思路
TypeScript 默认使用结构类型系统做类型校验:只要两个类型的内部结构完全一致,就会判定二者兼容。你示例中type A和type B的函数签名结构完全相同,因此TS会认为二者可以互相替换。
要阻止b传入C,需要给两个函数类型添加独有标识,破坏结构一致性,模拟名义类型的校验效果。
具体实现方案
给每个函数类型追加一个唯一的类型层面标记即可,标记不会影响运行时逻辑:
// 用unique symbol保证标记全局唯一,不会和其他属性冲突 const AFuncTag = Symbol('AFunc'); const BFuncTag = Symbol('BFunc'); // 给函数类型交叉上独有标记属性 type A = ((a: string) => void) & { [AFuncTag]: true }; type B = ((b: string) => void) & { [BFuncTag]: true }; // 定义函数时用类型断言打上对应标记,运行时不会真的添加属性 const a = ((a: string) => {}) as A; const b = ((b: string) => {}) as B; function C(func: A) { // ... } C(a); // 类型校验通过 C(b); // 直接报错:类型“B”的参数不能赋给类型“A”的参数,属性[AFuncTag]在类型B中不存在
也可以封装通用的名义函数类型工具,简化重复定义:
type NominalFunction<Param, Return, Tag extends string> = ((p: Param) => Return) & { __funcTag: Tag }; // 直接传入不同Tag即可生成互不兼容的同签名函数类型 type A = NominalFunction<string, void, 'A'>; type B = NominalFunction<string, void, 'B'>;
内容的提问来源于stack exchange,提问作者display name
相关产品推荐
相关产品推荐

