Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

115
Vistas
Function to get object from list of implementations in class by type of implementation. (typescript generics)

I have a list of Components in a class Entity. These components extend the interface Component.

class Entity {
  ...
  const components: Component[] = [];
  ...
}

Where specific components implements the interface Component

class SpecificComponent0 implements Component { ... }

Now I want to query the entity instance e and get a component if it matches the type fed into the query, something like this:

const specificComponent0 = e.getSpecificComponent<SpecificComponentClass0>();

Or perhaps like this

const specificComponent0 = e.getSpecificComponent(instanceof SpecificComponentClass0)

But I can't seem to figure out a way to do it in the entity's get function.

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

This is a tricky one as you are mixing runtime and build-time concerns. Referring to the examples you suggested:

const specificComponent0 = e.getSpecificComponent<SpecificComponentClass0>();

This definitely isn't going to work, because the angle brackets specify a "Type Parameter", which only exists at build time. Since what you are trying to do involves logic, you need to pass something into the function at runtime to help it pick the correct element.

const specificComponent0 = e.getSpecificComponent(instanceof SpecificComponentClass0)

The return value of the instanceof operator is a boolean value. You are passing either true or false into this function, which isn't very useful.

You have two problems here.

  1. You want to pass something into the function that will allow you to select the right component
  2. I am assuming you want the function to return a component narrowed to the correct type, rather than typed generically as Component

Problem 1 can be solved by passing in the type Constructor function and then matching it with the constructor property of the instantiated Component

class Entity {
  constructor(private components: Component[]) {}

  getSpecificComponent(thing: new () => Component): Component | undefined {
    return this.components.find(component => component.constructor === thing)
  }
}

This works perfectly fine, but your getSpecificComponent function is going to return a value typed as Component | undefined, which isn't very useful if you want to use properties that only exist on one of the specific types.

To solve Problem 2 (without casting the return value, which you really shouldn't do), we need to

  1. Make the function generic and
  2. Turn the predicate that is passed into find into a user defined type guard to give the compiler a hint that if that function returns true, it can safely narrow the type down to the generic type
class Component {}

class OtherThing1 extends Component { name = 'thing1' }
class OtherThing2 extends Component { name = 'thing2' }
class OtherThing3 extends Component { name = 'thing3' }

const getNarrower = <T extends Component>(thingConstructor: new () => T) => 
  (thing: Component): thing is T => thing.constructor === thingConstructor

class Entity {
  constructor(private components: Component[]) {}

  getSpecificComponent<T extends Component>(thing: new () => T): T | undefined {
    return this.components.find(getNarrower(thing))
  }
}

const e = new Entity([new OtherThing1(), new OtherThing2()])

const thing = e.getSpecificComponent(OtherThing1)
console.log(thing) // [LOG]: OtherThing1: { "name": "thing1" } 

const thingNotHere = e.getSpecificComponent(OtherThing3)
console.log(thingNotHere) // [LOG]: undefined 
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda