Abhilash Ranjan
Abhilash Ranjan

Reputation: 21

Handle inline polymorphism in typescript

Have an implementation of polymorphism in typescript.

enum empType {
   developer = '1',
   qa = '2',
   manager = '3'
}

interface IEmployee {
   type: empType;
   ID: string;
   name: string;
   projectId: string;
}

interface IEmployeeDeveloper extends IEmployee {
   type: empType.developer;
   featureID: string;
   deadline: string;
}

interface IEmployeeQa extends IEmployee {
   type: empType.qa;
   bugCount: number;
}

interface IEmployeeManager extends IEmployee {
   type: empType. manager;
   reporteeIDs: string[];
}

If I need to have a config data holding a list of such employees

let employees: Record<string, IEmployee> = {
  'tom': {
      type: empType.developer,
      ID: '1',
      name: 'tom',
      projectId: '123',
      featureID: 'xxx',
      deadline: '01/01/2023'
   },
   'sham': {
      type: empType.qa,
      ID: '12',
      name: 'sham',
      projectId: '123',
      bugCount: 10000
   },
   'harry': {
      type: empType.manager,
      ID: '3',
      name: 'harry',
      projectId: '123',
      reporteeIDs: ['1', '2']
   },
}

While trying to compile the code, I am getting such error.

⨯ Unable to compile TypeScript:
error TS2322: Type '{ type: empType.developer; ID: string; name: string; projectId: string; featureID: string; deadline: string; }' is not assignable to type 'IEmployee'.
  Object literal may only specify known properties, and 'featureID' does not exist in type 'IEmployee'.

featureID: 'xxx',
       ~~~~~~~~~~~~~~~~
error TS2322: Type '{ type: empType.qa; ID: string; name: string; projectId: string; bugCount: number; }' is not assignable to type 'IEmployee'.
  Object literal may only specify known properties, and 'bugCount' does not exist in type 'IEmployee'.

bugCount: 10000,
       ~~~~~~~~~~~~~~~
 error TS2322: Type '{ type: empType.manager; ID: string; name: string; projectId: string; reporteeIDs: string[]; }' is not assignable to type 'IEmployee'.
  Object literal may only specify known properties, and 'reporteeIDs' does not exist in type 'IEmployee'.

reporteeIDs: ['1', '2'],
          ~~~~~~~~~~~~~~~

If instead we try to initialize like this

let employees: Record<string, any> = /same config code as above/

Then I am able to compile. However I want my variables to be properly typed and I do not prefer using any in my type definition.

Another way is

let employees: Record<string, IEmployee | IEmployeeDeveloper | IEmployeeQa | IEmployeeManager> = /same config code as above/

The issue with this is that in near future I will create many types of IEmployee. Then I will have to change the type of employees everytime I do such a thing. Also need to update all those place where I am using this variables.

How can we handle such scenarios in typescript.

Upvotes: 2

Views: 240

Answers (1)

Eduard
Eduard

Reputation: 1374

Here is how you can do it using Union Types. Read more here

type EmployeeItem = IEmployeeDeveloper | IEmployeeQa | IEmployeeManager;

let employees: Record<string, EmployeeItem> = {
  'tom': {
      type: empType.developer,
      ID: '1',
      name: 'tom',
      projectId: '123',
      featureID: 'xxx',
      deadline: '01/01/2023'
   },
   'sham': {
      type: empType.qa,
      ID: '12',
      name: 'sham',
      projectId: '123',
      bugCount: 10000
   },
   'harry': {
      type: empType.manager,
      ID: '3',
      name: 'harry',
      projectId: '123',
      reporteeIDs: ['1', '2']
   },
}

Upvotes: 3

Related Questions