Blake Steel
Blake Steel

Reputation: 378

Typescript passing generic class as parameter

This code is posing a problem to me:

var makeVariableOfClass = (sentClass: typeof Entity) => {
    var newEntity = new sentClass();
}

interface EntityProps {
    sentient: boolean;
}

class Entity {
    private sentient: boolean;
    constructor(props: EntityProps) {
        this.sentient = props.sentient
    }
}

class Person extends Entity {
    constructor() {
        super({sentient: true});
    }
}

class Wall extends Entity {
    constructor() {
        super({sentient: false});
    }
}

I'd like to be able to programmatically declare either a person or a wall (in this example), but the typing of Entity in makeVariableOfClass requires the EntityProps, even though I only want to send in a subset of things (Person and Wall). I understand that I could make sentClass be of type typeof Person | typeof Wall, but I'd like to be more scalable than that. Is there another way to get around this without typeof Person | typeof Wall | typeof ... ?

Upvotes: 1

Views: 1494

Answers (2)

Blake Steel
Blake Steel

Reputation: 378

I resolved it by sending in a constructor function, similar to y2bd's answer but not exactly the same:

let makeVariableOfClass = (createNewClass: () => Entity) => {
  return createNewClass();
}

Obviously this is a bit obtuse in this particular example, but it served my purposes of telling the abstract map class what types of walls to use for different map subclasses.

Upvotes: 0

y2bd
y2bd

Reputation: 6456

You could make sentClass be a constructor function with zero parameters that returns something that is compatible with Entity:

let makeVariableOfClass = <TEntity extends Entity>(
  sentClass: new () => TEntity
) => {
  let newEntity = new sentClass();
  return newEntity;
};

const person = makeVariableOfClass(Person); // person: Person
const wall = makeVariableOfClass(Wall); // wall: Wall
const entity = makeVariableOfClass(Entity); // ERR since Entity does not have a zero-arg constructor
const date = makeVariableOfClass(Date); // ERR since new Date does not produce Entity-compatible value

Upvotes: 3

Related Questions