Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Type narrowing using factory function for union type, discriminators and Partial<T>

I need to implement a factory function that creates an instance of a subtype – the factory function accepts the type discriminator plus a subset of properties that should be populated via Partial<T>.

This is a minimal code example:

type TypeA = {
  discriminator: 'A';
  aProp: string;
};

type TypeB = {
  discriminator: 'B';
  bProp: string;
};

type TypeX = TypeA | TypeB; // either of the two types

type TypeDiscriminator = TypeX['discriminator']; // "A" | "B"

function createInstance(discriminator: TypeDiscriminator, partial: Partial<TypeX>) {
  switch (discriminator) {
    case 'A':
      return { ...partial, discriminator: 'A' } as TypeA;
    case 'B':
      return { ...partial, discriminator: 'B' } as TypeB;
    default:
      throw Error();
  }
}

// Question: This should infer type to 'TypeA' (but it is TypeA | TypeB instead)
export const a = createInstance('A', { aProp: 'foobar' });

// this works, but is actually invalid (aProp does not exist on TypeB and should be caught as error)
export const b = createInstance('B', { aProp: 'foobar' }) as TypeB;

How would this be properly be implemented, without alterting the parameter list of createInstance?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

This works:

function createInstance<D extends TypeDiscriminator>(
  discriminator: D,
  partial: Partial<Extract<TypeX, { discriminator: D }>>
) {}

It picks the right type based on the discriminator given.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading