Search code examples
typescriptconditional-types

How do I get conditional types to work in this example from the official Typescript documentation?


I was looking at the typescript docs and landed on this page on conditional types.

I was trying to implement the createLabel function in this way:

interface IdLabel {
  id: number /* some fields */;
}
interface NameLabel {
  name: string /* other fields */;
}
type NameOrId<T extends number | string> = T extends number
  ? IdLabel
  : NameLabel;

function createLabel<T extends number | string>(nameOrId: T): NameOrId<T>  {
  const label: NameOrId<T> = (typeof nameOrId === 'number') ? { id: nameOrId }: { name: nameOrId} ;
  return label;
}

Unfortunately I get an error on the label creation

Type '{ id: number; } | { name: string; }' is not assignable to type 'NameOrId<T>'.
  Type '{ id: number; }' is not assignable to type 'NameOrId<T>'.

What am I doing wrong?


Solution

  • The issue with the code is that TypeScript is unable to infer the correct type of the returned value from the createLabel function. To fix this, you can use a type assertion to explicitly tell TypeScript what the type of the returned value should be.

    Here's the corrected code:

    interface IdLabel {
      id: number /* some fields */;
    }
    
    interface NameLabel {
      name: string /* other fields */;
    }
    
    type NameOrId<T extends number | string> = T extends number
      ? IdLabel
      : NameLabel;
    
    function createLabel<T extends number | string>(nameOrId: T): NameOrId<T> {
      return typeof nameOrId === "number"
        ? { id: nameOrId } as NameOrId<T>
        : { name: nameOrId } as NameOrId<T>;
    }
    
    const Name = createLabel("5"); // Type is NameLabel
    const Id = createLabel(5); // Type is IdLabel
    

    Playground