如何将泛型类型限制为与另一个泛型类型相同的子类型?

时间:2019-05-23 12:51:19

标签: typescript generics

我想声明一个表示某些对象变化的类型。

例如:

const test: SomeType = {
    a: 1,
    b: "foo"
};

const changing1: Changing<SomeType> = {
    obj: test,
    was: {
        a: test.a
    },
    now: {
        a: 3
    }   // Correct one

const changing2: Changing<SomeType> = {
    obj: test,
    was: {
        a: test.a
    },
    now: {
        b: "bar"
    }   // Incorrect one

我已经在尝试这样做:

type Changing<T, K = {[R in keyof T]: T[R]}, P extends K = {[R in keyof K]: K[R]}> = {
    obj: T,
    was: K,
    now: P
}

这个想法是将P限制为K的扩展,但具有相同的成员。似乎无法正常工作。

1 个答案:

答案 0 :(得分:0)

我们可以使用映射类型为每个属性构建所有可能的选项,然后将所有选项提取到联合中。这将使您期望是错误的情况变成错误:

interface SomeType {
    a: number,
    b: string
}
const test: SomeType = {
    a: 1,
    b: "foo"
};

const changing1: Changing<SomeType> = {
    obj: test,
    was: {
        a: test.a
    },
    now: {
        a: 3
    } 
}

const changing2: Changing<SomeType> = { // error
    obj: test,
    was: {
        a: test.a
    },
    now: {
        b: "bar"
    }  
}

type Changing<T> = {
    [P in keyof T]: {
        obj: T,
        was: Pick<T, P>
        now: Pick<T, P>
    }
}[keyof T]