首页 > 解决方案 > 在对象内将一种 TypeScript 类型与另一种类型交换

问题描述

我有以下类型:

type Target = number | undefined;

type MyObject = {
    some: string;
    properties: string;
    id: Target;
}

我想提出一种通用的方法来替换Targetnumber例如:

type MyObjectTransformed = TargetToNumber<MyObject>;

/**
 * MyObjectTransformed is now:
 * 
 * {
 *     some: string;
 *     properties: string;
 *     id: number;
 * }
 */

如果您知道Target总是在id现场,这很容易,我不需要帮助。

但如果Target可以在任何地方呢?像这样也应该有效:

TargetToNumber<{
    some: string;
    other: Target;
    properties: string;
}>

更糟糕的是......它也需要在嵌套时工作!像这样仍应替换Targetnumber

TargetToNumber<{
    some: string;
    properties: string;
    nested: {
        arbitrarily: {
            deep: Target;
        };
    };
}>

如果你好奇我为什么要做这么奇怪的事情,这就是我问的原因

标签: typescripttypescript-generics

解决方案


使用条件类型:如果任意类型TA或 的子类型A,我们将其替换为B,否则如果它是对象类型,我们递归映射属性,否则我们将类型保留为T

type TargetToNumber<T> = SubstituteType<T, Target, number>;

type SubstituteType<T, A, B> =
    T extends A
    ? B
    : T extends {}
    ? { [K in keyof T]: SubstituteType<T[K], A, B> }
    : T;

如果您只想完全替换A并单独保留子类型A(例如never,始终是子类型...),您可以替换T extends A[A, T] extends [T, A]以测试它们是否为相同类型。

游乐场链接


推荐阅读