Typescript深度替换多种类型

2024-04-28

我将 mongodb 与 @types/mongodb 一起使用。这为我提供了一个很好的 FilterQuery 接口,用于我的 mogodb 查询形状文档集合。在我的域对象类中,我有一些额外的逻辑,例如将日期转换为时刻对象或将浮点数转换为 BigNumber 对象。

对于我的查询,我需要将它们转换回来,例如,需要将 Moment 对象转换为日期对象等等。为了避免重复和维护单独的接口(仅用于查询),我想到使用映射类型将所有 Moment 类型替换为 Date 类型

type DeepReplace<T, Conditon, Replacement> = {
  [P in keyof T]: T[P] extends Conditon
    ? Replacement
    : T[P] extends object
    ? DeepReplace<T[P], Conditon, Replacement>
    : T[P];
};


class MyDoaminClass {
  date: Moment;
  nested: {
    date: Moment;
  };
}

const query: DeepReplace<MyDoaminClass, Moment, Date> = {
  date: moment().toDate(),
  nested: {
    date: moment().toDate()
  }
};

这基本上是可行的,但我有大约 4-5 个这样的类型需要更换。是否有一种优雅的方法来链接多个 DeepReplace 类型,甚至更好:在一个地方指定所有类型替换?我想避免类似的事情type ReplaceHell = DeepReplace<DeepReplace<DeepReplace<MyDoaminClass, Moment, Date>, BigNumber, number>, Something, string>


假设您想“一次性”进行更换并且not作为“链”(意味着你不打算替换X with Y and then代替Y with Z),那么你可以重写DeepReplace建立工会M对应于的映射元组[Condition1, Replacement1] | [Condition2, Replacement2] | ...。所以你的老DeepReplace<T, C, R>将会DeepReplace<T, [C, R]>。定义如下:

type DeepReplace<T, M extends [any, any]> = {
    [P in keyof T]: T[P] extends M[0]
    ? Replacement<M, T[P]>
    : T[P] extends object
    ? DeepReplace<T[P], M>
    : T[P];
}

where Replacement<M, T>查找映射元组M where T可分配给条件并返回相应的替换,定义如下:

type Replacement<M extends [any, any], T> =
    M extends any ? [T] extends [M[0]] ? M[1] : never : never;

让我们看看它是否适用于我将在这里弥补的某些类型。鉴于以下情况:

interface DateLike {
    v: Date;
}
interface StringLike {
    v: string;
}
interface NumberLike {
    v: number;
}

interface Original {
    a: {
        dat: DateLike;
        str: StringLike;
        num: NumberLike;
        boo: boolean
    },
    b: {
        arr: NumberLike[]
    },
    c: StringLike,
    d: number
}

让我们替换...Like types:

type Replaced = DeepReplace<Original, 
  [DateLike, Date] | [StringLike, string] | [NumberLike, number]
>

/* equivalent to
type Replaced = {
    a: {
        dat: Date;
        str: string;
        num: number;
        boo: boolean;
    };
    b: {
        arr: number[];
    };
    c: string;
    d: number;
}
*/

这样就可以了。


请注意,调用新DeepReplace<T, [C, R]>这可能与原始情况具有相同的边缘情况DeepReplace<T, C, R>有。例如,工会如{a: string | DateLike}不会被映射。我会认为对这些的任何调整都超出了问题的范围。


好的,希望有帮助;祝你好运!

Playground 代码链接 https://www.typescriptlang.org/play/#code/C4TwDgpgBAIhFgEoIDYEMDGEA8AVANFALJQQAewEAdgCYDOUA2mlSISyALoB8UAvFADeAWABQUCUwAKUAJZUoAawggA9gDMouTgC4tjKZ1IVq9YowAMnMZKgB+KMjDosAW2rBsRQrgM8bknq+hsaUtAyqAEYAVhAYwAESDnAITi44wZyERNyJUEF+ANxiAL5iYqCQjqiYEO5UniTkYWbMrOysWVq8fHlNJuFQHPZM2qGmDIxElpxGDtMAjEZ6VBAAbhAATvlQqxubxaLlovKUm+q1sGiUADKyykJ5a3ow1xCHZScNWxdYUADKwE28gA5ncHiJxJJnlA6EDQR8xKcfpcAHIAV1ckS24OgkNsMKomOxB1Kx2R50uAHlgSD5GgUI8oRI0Hp8bZJDRri83rjDhzJHDNnpAcCqGD7u88rYia49BisTjJfyBVBIqpVHp1aoUBAWHkSvg8pE2dLJGhNsKoAqSbjGNZmVBDXkMCL4eLcUbHTQVsStmSjqJKtA0rUaPxYPAkDUsNgabI6VQGYRGK9bpLCGmIEYAD5MUWgz2w90g3NMG1K5SEWUk-yiAD0ACpSABHdGyNYMjxQYCqCrgEMxiDhgTslmmx22LnAHmUFUCoV6IUIs0SWW+xWkyeSbVajW6ljzp1Hk1M1VDS0bkn2o8lI+u4tikFHn27P1bz6N+tiIA

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Typescript深度替换多种类型 的相关文章

随机推荐