how to implement a function with optional parameter and conditional type

139 Views Asked by At

First a function implementation with only conditional types that works

interface IdLabel {
  id: number /* some fields */;
}
interface NameLabel {
  name: string /* other fields */;
}

type NameOrId<T extends number | string> = T extends number ? IdLabel : NameLabel;

type createLabelType = <T extends number | string>(idOrName: T) => NameOrId<T>;

const createLabel: createLabelType = idOrName => {
  if (typeof idOrName === 'number') return { id: idOrName } as NameOrId<typeof idOrName>;
  return { name: idOrName } as NameOrId<typeof idOrName>;
};

const nameLable = createLabel('str'); // nameLable has NameLabel type
const idLable = createLabel(1); // idLable has IdLabel type

how to do something similar based on optional id parameter? is it possible?

/** expample 2. HOW TO FORCE IT WORKS? */
interface IdLabel {
  id: number /* some fields */;
}
interface NameLabel {
  name: string /* other fields */;
}

type NameOrId<T extends number | undefined> = T extends number ? IdLabel : NameLabel;

type createLabelType = <T extends number | undefined>(id?: T) => NameOrId<T>;

const createLabel: createLabelType = id => {
  // *
  if (typeof id === 'number') return ({ id } as unknown) as NameOrId<typeof id>;
  return { name: id } as NameOrId<typeof id>;
};

const nameLable = createLabel(); // nameLable has IdLabel type, but I want to see NameLabel
const idLable = createLabel(1); // idLable has IdLabel type

without to cast unknown type Conversion of type '{ id: T; }' to type 'NameOrId<T>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.ts(2352)

typescript version "4.2.4" strictNullChecks false

0

There are 0 best solutions below