首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型记录深度替换多个类型

类型记录深度替换多个类型
EN

Stack Overflow用户
提问于 2020-02-27 15:59:33
回答 1查看 1.2K关注 0票数 4

我在@type/ mongodb中使用mongodb。这为我提供了一个很好的FilterQuery接口,用于莫干布对一组成形文档的查询。在我的域对象类中,我有一些额外的逻辑,比如将日期转换为矩对象或浮动到BigNumber对象。

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

代码语言:javascript
复制
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>这样的事情

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-27 16:23:44

假设您希望立即进行替换,而不是作为“链”(意味着您不打算用Y替换Y,然后将Y替换为Z),那么您可以重写DeepReplace以获取对应于[Condition1, Replacement1] | [Condition2, Replacement2] | ...的映射元组的联合M。所以你以前的DeepReplace<T, C, R>DeepReplace<T, [C, R]>。定义如下:

代码语言:javascript
复制
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];
}

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

代码语言:javascript
复制
type Replacement<M extends [any, any], T> =
    M extends any ? [T] extends [M[0]] ? M[1] : never : never;

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

代码语言:javascript
复制
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类型:

代码语言:javascript
复制
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}这样的联盟不会被映射。我会认为对这些的任何调整都超出了问题的范围。

好吧,希望这能帮上忙,祝你好运!

操场链接到代码

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60437172

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档