From the lib.es5.d.ts (the file with Record / Partial / etc definitions) you can see builtin definition of
/**
* Obtain the return type of a constructor function type
*/
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
So, the constructor is defined as
type Constructor<T> = abstract new (...args: any) => T;
And your function is
const getClassName = (someClass: Constructor<any>, name = someClass.constructor.name) => {
console.log(someClass)
console.log(someClass.constructor.name)
}
or
const getClassName = (someClass: abstract new (...args: any) => any, name = someClass.constructor.name) => {
console.log(someClass)
console.log(someClass.constructor.name)
}
If you want to use the class name and keep your class itself on type level, you can use Branded (oko Opaque) types:
type Constructor<T> = abstract new (...args: any) => T;
// I tend to name non-object subtipes camelCase
type className<T> = string & {__classNameOf: T}
// or
declare const classNameOfSymbol: unique symbol
type className2<T> = string & {[classNameOfSymbol]: T}
function getClassName<T> (someClass: Constructor<T>, name = someClass.constructor.name): className<T> {
return name as className<T>
}
new (...args: any[]) => any