bobleujr
bobleujr

Reputation: 1176

Override optional inherited nested properties in interfaces

I have the following interface:

export interface InterfaceA {
    propA?: any;
}

export interface MyBaseInterface extends InterfaceA {
    propA?: {
        nestedPropA?: {
            nestedNestedPropA: string;
            nestedNestedPropB: string;
        };
    };
};

Then I want to extend MyBaseInterface and inherit all my props but adding more, like it would result as follows

export interface MyNewInterface {
    propA?: {
        nestedPropA?: {
            nestedNestedPropA: string;
            nestedNestedPropB: string;
            nestedNestedPropC: string;
        };
    };
};

So I tried a few examples based on this question such as:

export interface MyNewInterface extends MyBaseInterface {
    propA?: MyBaseInterface['propA'] & {
        nestedPropA?: MyBaseInterface['propA']['nestedPropA'] & {
            nestedNestedPropC: string;
        };
    };
};

But it will say "MyBaseInterface does not have nestedPropA" (Since it is optional). If I make my props not optional, it won't override it. And finally if I make it extends Required<> it will force me further to implement props that I don't want to.

Can someone help me out? Thanks

Upvotes: 0

Views: 646

Answers (1)

ford04
ford04

Reputation: 74560

You apparently have reached the natural borders of interface inheritance. Afaik Lookup types cannot express this optional constraint and you also cannot use Conditional types for interfaces.

Type aliases offer much more flexibility in terms of type definition and composition of optional properties:

type A = {
  // your base properties
};

type B = A & {
  propA?: {
    nestedPropA?: {
      nestedNestedPropA: string;
      nestedNestedPropB: string;
    };
  };
}

type C = B & {
  propA?: {
    nestedPropA?: {
      nestedNestedPropC: string;
    };
  };
}

Note: You cannot define propA?: any; in A, as propA type would be widened to any when creating intersection types and you would loose the strong typing. You can simply prove that by:

type T1 = any
type T2 = string
type T3 = T1 & T2 // type T3 = any ; any wins

Here is a TS Playground with above example.

Upvotes: 1

Related Questions