'Properly pass class type on generic function to create new class of any type

I am trying to understand and learn more on generics in typescript and wanted to know why this does not work. I have spent a lot of hours reading about generics and types but for the life of me I cannot understand what I have done wrong.

Example:

abstract class Employee {
  constructor(
    public identifier: string
  ) {}
}

class FinanceEmployee extends Employee {
  empType: string;
  constructor(
    identifier: string
  ) {
    super(identifier);
    this.empType = "Finance";
  }
}

class MarketingEmployee extends Employee {
  empType: string;
  constructor(
    identifier: string
  ) {
    super(identifier);
    this.empType = "Marketing";
  }
}

type EmployeeType<T> = new (identifier: string) => T;

let count = 0;

function createEmployee<T>(ctor: EmployeeType<T>):void {
  const employee = new ctor(`employee-${count++}`);
  console.log(employee.identifier);
  console.log(employee.empType);
}

createEmployee(FinanceEmployee);
createEmployee(MarketingEmployee);

Typescript errors and tells me that identifier and empType do not exist on type T...



Solution 1:[1]

Inside the createEmployee type, there isn't any information about what ctor actually returns, only that it's some type T.

You can add a constraint to T so that inside the function, we have more information about what T will actually be, and to also restrict what type of constructor can be passed in:

function createEmployee<T extends Employee & { empType: string }>(ctor: EmployeeType<T>): void {
  const employee = new ctor(`employee-${count++}`);
  console.log(employee.identifier);
  console.log(employee.empType);
}

Playground Link

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Titian Cernicova-Dragomir