Search code examples
typescript

Unable to use "never" in union compound type


I'm trying to initialize a class with an object as the input of the constructor, which will populate a field of the class.

However, the object can have one of two fields populated, which leads to an error when I'm trying to parse it inside the constructor.

I'm expecting the following (simplified) code to work:

type Props = { name: string; age: never } | { name: never; age: number };

class Person {
  data: Props;

  constructor(data: Props) {
    if (data.name !== undefined) {
      this.data = data;
    } else {
      this.data = { // This line raises the error
        ...data,
        age: data.age * 1.5, // Even when it's just "data.age" it still raises an error
      };
    }
  }
}

But I'm getting the following error:

Type '{ age: number; name: string; }' is not assignable to type '{ name: never; age: number; }'.
Types of property 'name' are incompatible.
Type 'string' is not assignable to type 'never'.


Solution

  • If a property is of type never, but is not optional, then it will be required… but no value can satisfy the requirement:

    TS Playground

    const noName: { name: never } = {}; /* Error
          ~~~~~~
    Property 'name' is missing in type '{}' but required in type '{ name: never; }'.(2741) */
    

    However, if the property is optional then there's no problem:

    const noName: { name?: never } = {}; // Ok
    

    So, to fix your example, just mark the excluded properties as optional, and everything will compile:

    TS Playground

    type Props =
      | { name: string; age?: never }
      | { name?: never; age: number };