2

I'm trying to get the type/class from an custom object instance. This will then be used as a type parameter passed to a generic function rather than just use the 'any' type.

I've tried foo.prototype, Object.getPrototypeOf(foo), typeof foo, foo.constructor, foo.constructor.name etc but haven't yet found a way to return the objects's type/class itself. The example below gives an idea of what I want to achieve - it doesn't work here because constructor.name only returns the name of the type:

var vehicle 

if (selected == 'car') { 
vehicle = new Car() 
} else { 
vehicle = new Bike()  
} 

var vehicleType = vehicle.constructor.name

buildVehicle<vehicleType>(vehicle) 

buildVehicle<T>(vehicle:T) { 
    do stuff… 
}

I'm pretty new to typescript and javascript so I'm not sure this is even possible, but hopefully there is a way to do this.

Thanks for any help on this.

5
  • Possible duplicate of Get an object's class name at runtime Commented Jul 23, 2019 at 21:20
  • Typescript types don't exist at runtime, so there's no way you'll be able to get vehicleType out of an object instance and then pass this as a type parameter to buildVehicle<vehicleType>(vehicle). If you think about it, buildVehicle<vehicleType>(vehicle) requires a type at compile-time, but if your code did work you'd only be able to get that type at run-time. Commented Jul 23, 2019 at 21:34
  • @MichałTkaczyk - that link only gets the name - I want to get the type itself Commented Jul 24, 2019 at 11:19
  • @Collierre - I thought that was only a limitation if I wanted to get an interface (ie you can get classes but not interfaces at runtime). I know if I explicitly put buildVehicle<Car>(vehicle) it will work fine - I just don't know how I can get a reference to Car (or Bike) from the instance. Commented Jul 24, 2019 at 11:30
  • @TeMo, typescript is javascript at runtime, and in javascript at runtime you cannot get a class from one of its instances (though you can get the class name). Therefore you cannot in typescript either. Commented Jul 24, 2019 at 12:46

2 Answers 2

1

In your example you shouldn't add the type to the generic at all. TypeScript can infer the type in this context, because T is used a parameter.

// Use it like this: 
buildVehicle(vehicle);

If you really want to add the generic here, you could use typeof.

buildVehicle<typeof vehicle>(vehicle);

This is, in this case, equivalent to

buildVehicle<Car | Bike>(vehicle);

because it is not possible to determine which type vehicle actually has at compile time. It could only be determined at runtime. But since TypeScript types are lost during transpilation (as it transpiles to JavaScript), there is no way to do that with your current code.

You could, however, change your code to make it determinable at compile time.

if (vehicle instanceof Car) {
   buildVehicle<Car>(vehicle); // Vehicle is narrowed down to type "Car"
} else if (vehicle instanceof Bike) { // else would suffice if only 2 possible types
   buildVehicle<Bike>(vehicle); // Vehicle is narrowed down to type "Bike"
}

Though, in your case, this would probably not make much sense.

Sign up to request clarification or add additional context in comments.

3 Comments

Not sure about that - the type might be inferred correctly, but I think I should be able to pass in a type parameter to make this explicit.
If you want to add the type, it needs to be a union type as the other answer stated. Since the type can be dynamically changed at runtime, the variable is of type Bike | Car. Since the generic information is lost at runtime, you can't do much about it.
Thanks for clarifying. Accepting this as the answer as it seems to cover all the options including use instanceof to get the exact type at compile time. I will go with the more compact union type Bike|Car method for now and switch to the more verbose conditional checks on instanceOf if I need the extra precision. Thanks to all contributors who helped with this (I have upvoted all answers independently).
0

Try to use type union: type Vehicle = Bike | Car;

3 Comments

Add more relevant data and make your A better
This works and seems better than using any. If I cant find a way to get the exact type from the instance, I may well go with this as the next best thing. Will see if any other ideas turn up here :)
Another alternative would be buildVehicle(vehicle: Car|Bike) {

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.