TypeScriptを使用して実行時にオブジェクトのクラス/タイプ名を取得することは可能ですか?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
TypeScriptを使用して実行時にオブジェクトのクラス/タイプ名を取得することは可能ですか?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
回答:
class MyClass {}
const instance = new MyClass();
console.log(instance.constructor.name); // MyClass
console.log(MyClass.name); // MyClass
ただし、縮小コードを使用すると名前が異なる可能性があることに注意してください。
let instance: any = this.constructor; console.log(instance.name);
anyあるconsole.log(instance.constructor['name']);
interface Function { name: string; }これにより、「ネイティブ」定義が拡張されます。
MyClass.nameコードを縮小すると、うまく機能しません。それはクラスの名前を縮小するからです。
パーティーに遅れるのはわかっていますが、これもうまくいくことがわかりました。
var constructorString: string = this.constructor.toString();
var className: string = constructorString.match(/\w+/g)[1];
あるいは...
var className: string = this.constructor.toString().match(/\w+/g)[1];
上記のコードは、コンストラクターコード全体を文字列として取得し、正規表現を適用してすべての「単語」を取得します。最初の単語は「関数」でなければならず、2番目の単語はクラスの名前でなければなりません。
お役に立てれば。
私の解決策は、クラス名に依存しないことでした。object.constructor.nameは理論的に機能します。しかし、IonicのようなものでTypeScriptを使用している場合、本番環境に入るとすぐに、Ionicの本番モードはJavascriptコードを最小化するため、炎上します。したがって、クラスには「a」や「e」などの名前が付けられます。
私がやったことは、コンストラクターがクラス名を割り当てるすべてのオブジェクトにtypeNameクラスを含めることでした。そう:
export class Person {
id: number;
name: string;
typeName: string;
constructor() {
typeName = "Person";
}
はい、そうではありませんでした。しかし、将来的に縮小される可能性のあるものにコンストラクター。名前を使用すると、頭痛の種になるだけです。
の型定義にはプロパティがないanyため、最初にインスタンスをキャストする必要Functionがありnameます。
class MyClass {
getName() {
return (<any>this).constructor.name;
// OR return (this as any).constructor.name;
}
}
// From outside the class:
var className = (<any>new MyClass()).constructor.name;
// OR var className = (new MyClass() as any).constructor.name;
console.log(className); // Should output "MyClass"
// From inside the class:
var instance = new MyClass();
console.log(instance.getName()); // Should output "MyClass"
TypeScript 2.4(およびそれ以前の可能性がある)を使用すると、コードをさらにクリーンにすることができます。
class MyClass {
getName() {
return this.constructor.name;
}
}
// From outside the class:
var className = (new MyClass).constructor.name;
console.log(className); // Should output "MyClass"
// From inside the class:
var instance = new MyClass();
console.log(instance.getName()); // Should output "MyClass"
Property 'name' does not exist on type 'Function'.
(this as {}).constructor.nameまたは、実際にオートコンプリートを取得するため、(this as object).constructor.nameより優れていanyます:-)
Angular2では、これはコンポーネント名を取得するのに役立ちます:
getName() {
let comp:any = this.constructor;
return comp.name;
}
TypeScriptコンパイルは、最初はFunctionにプロパティ名がないため、エラーを発行するため、comp:anyが必要です。
element.nativeElement-ディレクティブでは、このようなコンポーネントの名前を取得して@Optional() element: ElementRef<HTMLElement>使用できます if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; }
完全なTypeScriptコード
public getClassName() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec(this["constructor"].toString());
return (results && results.length > 1) ? results[1] : "";
}
このソリューションは、縮小化後に機能しますが、メタデータでクラスを装飾する必要があります。
コード生成を使用して、エンティティクラスを次のようなメタデータで装飾します。
@name('Customer')
export class Customer {
public custId: string;
public name: string;
}
次に、次のヘルパーを使用します。
export const nameKey = Symbol('name');
/**
* To perserve class name though mangling.
* @example
* @name('Customer')
* class Customer {}
* @param className
*/
export function name(className: string): ClassDecorator {
return (Reflect as any).metadata(nameKey, className);
}
/**
* @example
* const type = Customer;
* getName(type); // 'Customer'
* @param type
*/
export function getName(type: Function): string {
return (Reflect as any).getMetadata(nameKey, type);
}
/**
* @example
* const instance = new Customer();
* getInstanceName(instance); // 'Customer'
* @param instance
*/
export function getInstanceName(instance: Object): string {
return (Reflect as any).getMetadata(nameKey, instance.constructor);
}
期待される型がすでにわかっている場合(たとえば、メソッドが共用体型を返す場合など)、型ガードを使用できます。
たとえば、プリミティブ型の場合、typeofガードを使用できます。
if (typeof thing === "number") {
// Do stuff
}
複合型の場合は、instanceof guardを使用できます。
if (thing instanceof Array) {
// Do stuff
}