If I pass a Class I'd like to return its type. Right now I cast the type after returning the parent's type.
I'd Like to avoid the casting and preserving all intellisense features, is there a way?
Below is an example of implementations and what I'd like to achieve
class Component {
get name(): string {
return this.constructor.name
}
}
class Direction extends Component {
x: number
y: number
constructor(x: number = 0, y: number = 0) {
super()
this.x = x
this.y = y
}
}
class Rectangle extends Component {
x: number
y: number
w: number
h: number
constructor(x: number, y: number, w: number, h: number) {
super()
this.x = x
this.y = y
this.w = w
this.h = h
}
}
class Entity {
components: Map<string, Component>
constructor(...components: Component[]) {
this.components = new Map()
components.forEach(component => this.add(component))
}
get(component: Function): Component | undefined {
return this.components.get(component.name)
}
add(component: Component) {
this.components.set(component.name, component)
}
}
const player = new Entity(
new Rectangle(100, 100, 100, 100),
new Direction(1, 1)
)
const shape = player.get(Rectangle) as Rectangle
const direction = player.get(Direction) as Direction
Example of what I'd like to have
get(component: Function): ?? return the child type somehow ?? | undefined {
return this.components.get(component.name)
}
const shape = player.get(Rectangle) // No casting
CodePudding user response:
Looks like you just need a generic so that the type of the given constructor is retained in the return type:
get<C extends new (...args: any[]) => any>(component: C): InstanceType<C> | undefined {
return this.components.get(component.name) as InstanceType<C>;
}
Since we're passing a class and not an instance, the type of component
should be a constructor. Then in the return type, to get the type of an instance, we use the built-in InstanceType
.
@kikon's shorter (and better) version:
get<T>(component: new (...args: any[]) => T): T | undefined {
return this.components.get(component.name) as T;
}
This removes the need for InstanceType
as it lets the compiler infer the instance type for us (as T
) and the generic constraint.