Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

113
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!