TypeScript条件类型与类型收窄问题:函数实现类型推导失效求助
解决TypeScript中事件调度函数内部类型收窄失效的问题
你的问题核心在于:虽然通过泛型+条件类型实现了函数调用时的类型约束,但函数内部无法通过event的类型收窄自动推导出对应data的类型。这是因为TypeScript无法将泛型参数E与data的条件类型结果建立关联,在函数内部data始终被视为联合类型,无法跟随event的收窄而细化。
方案一:使用判别式联合对象作为参数(推荐)
将event和data合并为一个符合EventObject类型的参数,利用TypeScript对判别式联合的原生支持,自动在switch分支中收窄整个对象的类型:
export type EventObject = { event: 'connected'; data: boolean; } | { event: 'more'; data: string; }; function dispatch(eventObj: EventObject) { switch(eventObj.event) { case 'more': const res = eventObj.data.indexOf('xxxx'); // 编译器自动识别data为string类型 break; case 'connected': const isConnected = eventObj.data; // 自动识别为boolean类型 break; default: break; } } dispatch({ event: 'more', data: true }); // 编译报错,提示data应为string dispatch({ event: 'connected', data: true }); // 类型校验正常
这种方式不需要额外的类型工具,完全依赖TypeScript的原生类型系统,代码更简洁且类型推导准确。
方案二:使用函数重载保持参数分离
如果必须保留event和data作为独立参数,可以通过函数重载明确每个事件对应的data类型:
export type EventObject = { event: 'connected'; data: boolean; } | { event: 'more'; data: string; }; // 定义重载签名,明确每个事件的参数类型 function dispatch(event: 'connected', data: boolean): void; function dispatch(event: 'more', data: string): void; // 实现函数(内部参数为联合类型) function dispatch(event: EventObject['event'], data: boolean | string): void { switch(event) { case 'more': // 重载已保证此时data是string,可安全断言 const res = (data as string).indexOf('xxxx'); break; case 'connected': const isConnected = data as boolean; break; default: break; } } dispatch('more', true); // 编译报错,提示data应为string dispatch('connected', true); // 类型校验正常
这种方式保留了原有的参数结构,但函数内部需要使用类型断言来细化data的类型,不过调用时的类型约束依然严格。
内容的提问来源于stack exchange,提问作者Corentin
相关产品推荐
相关产品推荐

