TypeScript:如何根据属性从联合类型中条件提取类型?
根据Message类型收窄Payload类型的实现方案
要实现通过message.type字符串类型推断对应payload类型,你可以借助TypeScript的条件类型和Extract工具类型完成,同时需要将listener定义为泛型函数,让type参数和回调的payload类型形成关联。
步骤1:定义用于推断Payload的泛型类型
先创建一个泛型类型InferMessagePayloadByType,它接收一个type类型参数,从AnyMessage联合类型中筛选出匹配该type的成员,再提取其payload类型:
type Message1 = { type: 'message1', payload: string } type Message2 = { type: 'message2', payload: boolean } type AnyMessage = Message1 | Message2; type AnyMessageType = AnyMessage['type'] // 核心类型:根据type推断对应的payload类型 type InferMessagePayloadByType<T extends AnyMessageType> = Extract<AnyMessage, { type: T }>['payload']
这里Extract<UnionType, ConditionalType>的作用是从联合类型UnionType中提取出符合ConditionalType条件的成员,之后通过['payload']获取该成员的payload类型。
步骤2:改造listener为泛型函数
将listener定义为泛型函数,让type参数的类型和回调的payload类型绑定,这样TypeScript就能自动根据传入的type推断出payload的正确类型:
const listener = <T extends AnyMessageType>( type: T, callback: (payload: InferMessagePayloadByType<T>) => any ) => { // 业务逻辑示例:比如模拟触发回调 if (type === 'message1') { callback('hello' as InferMessagePayloadByType<T>); } else { callback(true as InferMessagePayloadByType<T>); } }
使用示例
调用listener时,TypeScript会根据传入的type自动推断payload的类型,提供类型校验和提示:
// 传入'message1',payload自动推断为string类型 listener('message1', (payload) => { console.log(payload.toUpperCase()); // 类型合法,无报错 }); // 传入'message2',payload自动推断为boolean类型 listener('message2', (payload) => { console.log(payload ? '激活' : '关闭'); // 类型合法,无报错 }); // 如果传入错误的payload类型,TypeScript会直接报错 listener('message1', (payload) => { console.log(payload + 1); // 报错:string不能和number相加 });
内容的提问来源于stack exchange,提问作者Istvan Orban
相关产品推荐
相关产品推荐

