如何编写TypeScript函数,基于判别器映射两个联合类型?
基于判别器的联合类型映射函数实现
当然可以实现这个需求!TypeScript的条件类型和联合类型的判别特性,正好能帮我们编写一个能自动推断输出类型的map函数签名——让编译器根据输入的判别器字段,精准匹配对应的输出类型。
基础场景实现
先从你给出的In/Out联合类型示例入手,我们先定义一个映射辅助类型,用来关联输入和输出的判别器:
// 输入联合类型 type InA = { type: 'a', data: string }; type InB = { type: 'b', data: number }; type In = InA | InB; // 输出联合类型 type OutA = { type: 'a', data: Object }; type OutB = { type: 'b', data: Array<number> }; type Out = OutA | OutB; // 辅助类型:根据输入的type字段,匹配对应的输出类型 type MapInToOut<T extends In> = T extends { type: infer U } ? Extract<Out, { type: U }> : never;
接着给map函数加上这个泛型约束,就能实现自动类型推断:
function map<T extends In>(input: T): MapInToOut<T> { // 根据判别器编写转换逻辑 switch (input.type) { case 'a': return { type: 'a', data: {} } as MapInToOut<T>; case 'b': return { type: 'b', data: [input.data] } as MapInToOut<T>; default: throw new Error('Unknown type'); } } // 使用示例:编译器自动推断返回值为OutB const result = map({ type: 'b', data: 999 }); // result的类型将被自动推导为 { type: 'b', data: number[] }
你的实际场景优化版
你基于@titian-cernicova-dragomir答案修改的实现已经非常贴合业务场景了,我们再把它梳理得更清晰:
/** Http Request types **/ type RequestA = { type: 'names', url: '/names' }; type RequestB = { type: 'numbers', url: '/numbers' }; type Request = RequestA | RequestB; /** Response types **/ type ResponseA = { type: 'names', data: Array<string> }; type ResponseB = { type: 'numbers', data: Array<number> }; type Response = ResponseA | ResponseB; /** 辅助类型:根据请求的type字段,匹配对应的响应类型 */ type GetResponse<T extends Request> = T extends { type: infer U } ? Extract<Response, { type: U }> : never;
然后编写泛型的fetchData函数,利用辅助类型自动推断返回的Promise类型:
export function fetchData<T extends Request>(request: T): Promise<GetResponse<T>> { return fetch(request.url) .then(response => response.json()) .then(data => { return { type: request.type, data } as GetResponse<T>; }); } // 使用场景:编译器自动识别返回类型 const names = fetchData({ type: 'names', url: '/names' }); // names的类型是 Promise<ResponseA>(即 Promise<{ type: 'names', data: string[] }>) const numbers = fetchData({ type: 'numbers', url: '/numbers' }); // numbers的类型是 Promise<ResponseB>(即 Promise<{ type: 'numbers', data: number[] }>)
这个实现的核心逻辑是:用infer关键字提取输入类型的type字段值,再通过Extract工具类型从输出联合类型中筛选出匹配的类型,完美实现了基于判别器的类型映射与自动推断。
内容的提问来源于stack exchange,提问作者bingles
相关产品推荐
相关产品推荐

