无需重载,如何通过回调实现TypeScript类型收窄?
解决方案:泛型+映射类型替代函数重载
要实现根据传入的颜色筛选条件,让回调函数自动识别对应实体类型,不需要依赖函数重载,可以通过泛型约束+类型映射来实现,具体步骤如下:
1. 建立颜色与实体类型的映射
首先定义一个映射类型,把每个颜色和对应的具体实体类型绑定:
type ColorEntityMap = { red: RedEntity; blue: BlueEntity; green: GreenEntity; };
2. 将onMessage改为泛型函数
通过泛型参数关联颜色参数和回调函数的参数类型,让TypeScript能根据传入的颜色自动推导回调参数的具体类型:
function onMessage<TColor extends Color>( color: TColor, callback: (entity: ColorEntityMap[TColor]) => void ) { const lastEntity = getLastEntity(); if (lastEntity.color !== color) { return; } // 运行时已验证颜色匹配,可安全断言类型 callback(lastEntity as ColorEntityMap[TColor]); }
3. 可选:用类型守卫替代断言(更安全)
如果不想用类型断言,可以写一个自定义类型守卫,让TypeScript在编译期确认实体类型:
function isEntityOfColor<TColor extends Color>( entity: Entity<Color>, color: TColor ): entity is ColorEntityMap[TColor] { return entity.color === color; } // 修改onMessage中的判断逻辑 function onMessage<TColor extends Color>( color: TColor, callback: (entity: ColorEntityMap[TColor]) => void ) { const lastEntity = getLastEntity(); if (isEntityOfColor(lastEntity, color)) { callback(lastEntity); // 无需断言,TS自动识别类型 } }
效果验证
调用onMessage时,TypeScript会根据第一个参数的颜色,自动推导回调参数的具体类型:
onMessage("red", (entity) => { // 报错:类型"blue"不能赋值给类型"red" // entity.color === "blue"; // 正常识别:entity是RedEntity,可访问isRed属性 console.log(entity.isRed); }); onMessage("blue", (entity) => { console.log(entity.isBlue); // 正确识别为BlueEntity });
方案优势
相比函数重载,这种方式的扩展性更强:如果新增颜色和对应的实体类型,只需要更新ColorEntityMap即可,无需修改函数的重载定义,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者nehalist
相关产品推荐
相关产品推荐

