TypeScript中基础类型扩展可选类型的优化实现问询
问题描述
我定义了如下基础类型:
type BaseProps = { foo: boolean; bar?: string; };
该基础类型可扩展以下两种额外类型:
type WithOkButton = { useOkButton: boolean; onOK(): void; }; type WithCancelButton = { useCancelButton: boolean; onCancel(): void; }
我的目标是得到一个包含BaseProps以及上述额外类型所有组合的类型,组合情况包括:
- 不包含任何额外类型
- 同时包含两种额外类型
- 仅包含
WithOkButton - 仅包含
WithCancelButton
我可以通过以下方式实现需求,但写法过于繁琐,能否提供更优的实现方案?
type BaseWithOK = BaseProps & WithOkButton; type BaseWithCancel = BaseProps & WithCancelButton; type BaseWithBoth = BaseProps & WithOkButton & WithCancelButton; type ResultType = BaseProps | BaseWithOK | BaseWithCancel | BaseWithBoth;
补充说明
若需要支持三种按钮的所有组合,代码会变为如下形式,写法复杂度进一步提升:
type BaseProps = { foo: boolean; bar?: string; }; type A = { useA: boolean; onClickA(): void; }; type B = { useB: boolean; onClickB(): void; }; type C = { useC: boolean; onClickC(): void; }; type BasePropsWithA = A & BaseProps type BasePropsWithB = B & BaseProps type BasePropsWithC = C & BaseProps type BasePropsWithAB = A & B & BaseProps type BasePropsWithBC = B & C & BaseProps type BasePropsWithAC = A & C & BaseProps type BasePropsWithABC = A & B & C & BaseProps type Props = BaseProps | BasePropsWithA | BasePropsWithB | BasePropsWithC | BasePropsWithAB | BasePropsWithBC | BasePropsWithAC | BasePropsWithABC;
优化方案
可以通过泛型工具类型自动生成所有扩展组合,无需手动枚举每种情况,扩展性极强,新增扩展类型只需修改一处代码。
核心思路
- 定义工具类型
AllCombinations,递归遍历扩展类型的联合,生成所有可能的子集交集(单个扩展类型、多个扩展类型的组合)。 - 加上空集
{}覆盖“不包含任何扩展类型”的情况。 - 最终将基础类型与所有扩展组合交叉,得到目标类型。
代码实现(两种扩展类型场景)
type BaseProps = { foo: boolean; bar?: string; }; type WithOkButton = { useOkButton: boolean; onOK(): void; }; type WithCancelButton = { useCancelButton: boolean; onCancel(): void; }; // 生成联合类型的所有子集组合(单个/多个扩展类型的交集) type AllCombinations<U> = U extends infer T ? T | (T & AllCombinations<Exclude<U, T>>) : never; // 包含空集的所有扩展组合 type AllPossibleExtensions = {} | AllCombinations<WithOkButton | WithCancelButton>; // 最终目标类型 type ResultType = BaseProps & AllPossibleExtensions;
代码实现(三种扩展类型场景)
仅需修改扩展类型的联合参数,其余代码完全复用:
type BaseProps = { foo: boolean; bar?: string; }; type A = { useA: boolean; onClickA(): void; }; type B = { useB: boolean; onClickB(): void; }; type C = { useC: boolean; onClickC(): void; }; type AllCombinations<U> = U extends infer T ? T | (T & AllCombinations<Exclude<U, T>>) : never; type AllPossibleExtensions = {} | AllCombinations<A | B | C>; type Props = BaseProps & AllPossibleExtensions;
效果说明
ResultType/Props自动包含所有需要的组合:基础类型、仅单个扩展类型、任意多个扩展类型的组合。- 新增扩展类型时,只需将其加入
AllCombinations的泛型参数(如A | B | C | D),无需手动新增交叉类型和联合分支。
内容的提问来源于stack exchange,提问作者Evgeniy Pozdnyakov
相关产品推荐
相关产品推荐

