Home > Back-end >  How to check if the type of an object is a class?
How to check if the type of an object is a class?

Time:05-27

I'm trying to check if the type of an object is a class, any class at all.

This is what I've tried:

export type IsClass<T> = (
    T extends ({new (...args: any[]): any}) ? true : false
)
class SomeClass {}
const a: IsClass<number> = false;
const b: IsClass<SomeClass> = false;
const c: IsClass<({new(): any})> = true;

Last I checked, it was not possible to tell if a type was an object or a class, but I couldn't find the Typescript issue pertaining to it.

How can I check if the type of an object is a class?


Bonus: this is how to check it with actual code. It doesn't translate to type logic.

function isClass(target: any) {
  return typeof target === "object" && (/^(object|array)$/i.test(target.constructor.name) === false)
}

From what I can tell, Typescript knows the difference between an object and a class... sort of:

const a = {};
class B{};
const testA = new a();  //error: This expression is not constructable.
const testB = new B();

But I guess it can't tell that testB is a class object.

CodePudding user response:

Typescript has two separate namespaces. One for code and one for types. There is no way no classes at the code level. Types are only analyzed at compile time. This is because Typescript is a superset of Javascript. So there are no things like for example in Java, where you have a reflection API to check type structure.

What is your root problem? What are you aiming to achieve?

CodePudding user response:

You can make use of type predicates:

// returns true if 'target' is a constructor and tells TS that as well
function isClass(target: any): target is { new (...args: any[]): any } {
  // one change made: 'target && ...' to check for null
  return target && typeof target === "object" && (/^(object|array)$/i.test(target.constructor.name) === false)
}

// ...

if (isClass(myTarget)) new myTarget(); // works

CodePudding user response:

Actually, now that I think about this further. If I understood right, you may get close to what you are aiming at with the prototype property of javascript object:

class Cat {
  static type = "cat";

  public act = () => {
    console.log('scratch')
  }
}


const array = [
  new Cat(),
  {
    something: 'else'
  }
]


array.forEach(element => {
  console.log((element as any).prototype)
})

When you create a class with Typescript, it will get its own prototype. With a simple object, it remains empty.

  • Related