Stan Luo
Stan Luo

Reputation: 3889

Typescript - conditional property based on another property

When defining a type, can we make one property required based on another property?

An example is:

type Parent = {
  children?: Child[];
  childrenIdSequence: string[]; // Only make this required when `children` is given
}

Upvotes: 2

Views: 2844

Answers (1)

kaya3
kaya3

Reputation: 51034

What you want can be achieved using a union type:

type Parent = {
  children: Child[],
  childrenIdSequence: string[]
} | {
  children: undefined
}

This means a Parent either has a children array and a childrenIdSequence array, or its children property is undefined and it is not guaranteed to have a childrenIdSequence array. The type can be control-flow narrowed by testing the children property:

function test(p: Parent): void {
    if(p.children) {
        // p: { children: Child[], childrenIdSequence: string[] }, so OK
        console.log(p.childrenIdSequence);
    } else {
        // p: { children: undefined }, so type error
        console.log(p.childrenIdSequence);
    }
}

However, there is a bit of a downside: the children property is required even if you want it to be undefined. You have to explicitly write a literal like { children: undefined } instead of just {}, otherwise it won't be of type Parent.

If you try declaring the type with children?: undefined as an optional property, then the union won't work because one branch is a structural subtype of the other, and the type in the function will be uselessly narrowed to p: never.

Upvotes: 3

Related Questions