替换打字稿类型的属性

时间:2018-07-30 17:38:08

标签: typescript

我有一个类型:

type first = {
    one: number;
    two: string;
    three: {
        four: string,
        five: number,
    }
}

它适用于我在应用程序的一部分中声明的变量的一个实例,但不适用于变量的另一个(第二个)实例。

适合于变量第二个实例的类型如下:

type second = {
    one: number;
    two: string;
    three: {
        four: string,
        five: number[], //difference
    }
}

我不想从头开始声明一种新类型,而希望通过替换属性first的类型来吸收现有类型three

我试图这样做:

type second = Pick<first, Exclude<keyof first, 'three'>> & { 
    three: {
        four: string,
        five: number[], //difference
    } 
}

但是它给了我一个错误,我在悬停时得到了这个类型定义:

type second = {
    one: number;
    two: string;
    three: {
        four: string,
        five: number,
    };
    three: {
        four: string,
        five: number,
    };
}

注意2个属性three

我在做什么错了?

2 个答案:

答案 0 :(得分:1)

您的解决方案应该起作用,我只有两个发现:

  1. 您可以在类型查询中向下一级使用相同的方法,而无需重写内部对象

  2. 注意交集类型,假设它们的行为与手工生成的类型完全相同并不总是正确的。参见this question。我们可以解决使用附加映射类型使类型变平的问题。

记住这些,这就是我要做的:

type first = {
    one: number;
    two: string;
    three: {
        four: string,
        five: number,
    }
}

type Identity<T> = { [P in keyof T]: T[P] }
type Replace<T, K extends keyof T, TReplace> = Identity<Pick<T, Exclude<keyof T, K>> & {
    [P in K] : TReplace
}>

type second = Replace<first, 'three', Replace<first['three'], 'five', number[]>>
let d: second = {
    one: 1,
    two: "",
    three : {
        four: "",
        five: [0]
    }
}

Playground link

答案 1 :(得分:0)

您可以尝试通过使用联合来替换类型定义的一部分。以下是过度简化:

type SecondType = FirstType & {
   three: {
        four: string,
        five: number[],
    }
  };

上述解决方案会给您带来麻烦。一个简单的联合并没有真正取代属性“三”,它实际上为属性“三”和“五”创建了两个相互冲突的定义。每当您尝试访问它们时,您的 IDE 都会向您发出警告。

解决方案是删除该属性,然后将其重新合并:

type SecondType = 
   Omit<FirstType, 'three'> & 
   { three: {
        four: string,
        five: number[]
   }};