Có thể lấy tên lớp / loại của đối tượng trong thời gian chạy bằng TypeScript không?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Có thể lấy tên lớp / loại của đối tượng trong thời gian chạy bằng TypeScript không?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Câu trả lời:
class MyClass {}
const instance = new MyClass();
console.log(instance.constructor.name); // MyClass
console.log(MyClass.name); // MyClass
Tuy nhiên: hãy cẩn thận rằng tên có thể sẽ khác khi sử dụng mã được rút gọn.
let instance: any = this.constructor; console.log(instance.name);
anylàconsole.log(instance.constructor['name']);
interface Function { name: string; }- điều này sẽ mở rộng định nghĩa "gốc".
MyClass.namesẽ không hoạt động tốt nếu bạn đang thu nhỏ mã của mình. Bởi vì nó sẽ thu nhỏ tên của lớp.
Tôi biết tôi đến bữa tiệc muộn, nhưng tôi thấy rằng điều này cũng hoạt động.
var constructorString: string = this.constructor.toString();
var className: string = constructorString.match(/\w+/g)[1];
Hoặc ...
var className: string = this.constructor.toString().match(/\w+/g)[1];
Đoạn mã trên lấy toàn bộ mã xây dựng thành một chuỗi và áp dụng biểu thức chính quy để nhận tất cả 'từ'. Từ đầu tiên phải là 'hàm' và từ thứ hai phải là tên của lớp.
Hi vọng điêu nay co ich.
Giải pháp của tôi là không dựa vào tên lớp. object.constructor.name hoạt động trên lý thuyết. Nhưng nếu bạn đang sử dụng TypeScript trong một cái gì đó như Ionic, ngay khi bạn đi vào sản xuất, nó sẽ bùng cháy vì chế độ sản xuất của Ionic làm giảm mã Javascript. Vì vậy, các lớp được đặt tên những thứ như "a" và "e."
Điều cuối cùng tôi đã làm là có một lớp typeName trong tất cả các đối tượng của tôi mà hàm tạo gán tên lớp cho. Vì thế:
export class Person {
id: number;
name: string;
typeName: string;
constructor() {
typeName = "Person";
}
Vâng, đó không phải là những gì được yêu cầu, thực sự. Nhưng việc sử dụng constructor.name trên một cái gì đó có khả năng bị thu nhỏ xuống đường chỉ là một sự đau đầu.
Xem câu hỏi này .
Vì TypeScript được biên dịch thành JavaScript, nên trong thời gian chạy, bạn đang chạy JavaScript, do đó, các quy tắc tương tự sẽ được áp dụng.
Trước tiên, bạn cần truyền ví dụ sang anyvì Functionđịnh nghĩa loại không có thuộc nametính.
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"
Với TypeScript 2.4 (và có khả năng sớm hơn), mã có thể sạch hơn:
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.namehoặc (this as object).constructor.nametốt hơn là anyvì sau đó bạn thực sự nhận được tự động hoàn thành :-)
Mã TypeScript đầy đủ
public getClassName() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec(this["constructor"].toString());
return (results && results.length > 1) ? results[1] : "";
}
Trong Angular2, điều này có thể giúp lấy tên thành phần:
getName() {
let comp:any = this.constructor;
return comp.name;
}
comp: bất kỳ là cần thiết vì trình biên dịch TypeScript sẽ phát sinh lỗi vì Hàm ban đầu không có tên thuộc tính.
element.nativeElement- Theo chỉ thị, bạn có thể lấy tên của thành phần như thế này @Optional() element: ElementRef<HTMLElement>và sau đó sử dụng if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; }
Giải pháp này hoạt động sau khi thu nhỏ hóa nhưng yêu cầu trang trí các lớp bằng siêu dữ liệu.
Chúng tôi sử dụng việc tạo mã để trang trí các lớp Thực thể của mình bằng siêu dữ liệu như vậy:
@name('Customer')
export class Customer {
public custId: string;
public name: string;
}
Sau đó tiêu thụ với người trợ giúp sau:
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);
}
Nếu bạn đã biết loại nào sẽ xảy ra (ví dụ: khi một phương thức trả về loại kết hợp ), thì bạn có thể sử dụng các loại bảo vệ.
Ví dụ: đối với các kiểu nguyên thủy, bạn có thể sử dụng bộ bảo vệ kiểu :
if (typeof thing === "number") {
// Do stuff
}
Đối với các loại phức tạp, bạn có thể sử dụng một bảo vệ thể hiện :
if (thing instanceof Array) {
// Do stuff
}