Reputation: 378
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
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
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