如何从对象类型派生TypeScript区分联合类型?
问题
假设我们有如下对象:
const originalObj = { foo: 'fooVal', bar: 'barVal' };
我需要编写一个工具类型,从该原始对象生成区分联合类型,联合的每个成员结构如下:
type Sample1 = { header: string; accessor: 'foo'; // 判别式 render?: (value: 'fooVal', original: typeof originalObj) => React.ReactNode; }; type Sample2 = { header: string; accessor: 'bar'; // 判别式 render?: (value: 'barVal', original: typeof originalObj) => React.ReactNode; };
手动编写的目标类型是:
type OriginalObjMappedToUnionOfSamples = Sample1 | Sample2;
现在需要实现一个工具类型GetDiscriminatedUnionOfSamples,仅给定原始对象类型时自动生成上述联合类型,达到如下效果:
type WhatIWant = GetDiscriminatedUnionOfSamples<typeof originalObj>;
解决方案
可以通过TypeScript的映射类型和索引访问类型实现这个工具类型,核心是遍历原始对象的所有键,为每个键生成对应结构后自动合并为联合类型。
实现代码如下:
import type { ReactNode } from 'react'; type GetDiscriminatedUnionOfSamples<T extends object> = { [K in keyof T]: { header: string; accessor: K; render?: (value: T[K], original: T) => ReactNode; }; }[keyof T];
代码说明
- 遍历键生成结构:
{ [K in keyof T]: ... }会遍历原始类型T的所有键K,为每个键生成一个包含header、accessor和可选render的对象类型。 - 类型绑定:
accessor的类型直接绑定为当前键的字面量类型(比如'foo'),render函数的value参数类型绑定为原始对象中该键对应的值类型(比如'fooVal'),original参数则绑定为整个原始对象的类型。 - 转为联合类型:通过
[keyof T]索引访问映射后的对象类型,TypeScript会自动将所有单成员结构合并成一个联合类型。
验证效果
用题目中的originalObj测试:
const originalObj = { foo: 'fooVal', bar: 'barVal' }; type WhatIWant = GetDiscriminatedUnionOfSamples<typeof originalObj>;
此时WhatIWant的类型等价于手动编写的Sample1 | Sample2,完全符合需求。
内容的提问来源于stack exchange,提问作者Abe Caymo
相关产品推荐
相关产品推荐

