Matus Zamborsky
Matus Zamborsky

Reputation: 98

Why I can't omit properties from already omitted type?

I have simple case of omitting properties from another already omitted type:

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

interface A {
  x: string;
  y: number;
}

interface B extends A {
  z: Date;
  w: boolean;
}

type OmitA<T extends A> = Omit<T, 'x'>;
type OmitB<T extends B> = Omit<OmitA<T>, 'z'>;

The type OmitA has only property 'y' as expected. But the OmitB type throws error:

Type '"z"' does not satisfy the constraint 'Exclude<keyof T, "x">'. ts(2344)

Is this a bug or is there a problem with this code ?

Update 1

It looks like it works if I change the OmitB type to:

type OmitB<T extends B> = Omit<OmitA<T & B>, 'z'>;

which looks unnecessary to me.

Upvotes: 3

Views: 168

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249466

This is a limitation of the way you define Omit, K must be a keyof T. But since T is an unresolved type parameter typescript can't figure out if Omit<T, 'x'> will really contain z (more like it does not bother). There are ways to get around this, but the simplest solution would be to use the definition of Omit that will be added soon in typescript 3.5 (PR) which does not require K to extend keyof T

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>; // no constraint as in the new Omit in 3.5

interface A {
    x: string;
    y: number;
}

interface B extends A {
    z: Date;
    w: boolean;
}

type OmitA<T extends A> = Omit<T, 'x'>;
type OmitB<T extends B> = Omit<OmitA<T>, 'z'>; // works fine now

Upvotes: 2

Related Questions