런타임에 객체의 클래스 이름을 얻습니다.


271

TypeScript를 사용하여 런타임에 객체의 클래스 / 유형 이름을 가져올 수 있습니까?

class MyClass{}

var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"

3
여기를 참조 하십시오 . 런타임에 JavaScript를 실행하고 있습니다.
Matt Burland

1
그래도 TypeScript 파일에서 생성자 이름을 어떻게 얻습니까? TypeScript 메서드 (.ts 파일)에서는 this.constructor.name을 수행 할 수 없습니다.
sheldon_cooper

답변:


461

간단한 답변 :

class MyClass {}

const instance = new MyClass();

console.log(instance.constructor.name); // MyClass
console.log(MyClass.name);              // MyClass

그러나 축소 코드를 사용할 때는 이름이 다를 수 있습니다.


14
불행히도 MyClass.name은 ES6 기능이므로 IE11에서는 작동하지 않습니다.
begie

9
typescript는 이것에 오류를 발생시킵니다. 해야 할 것let instance: any = this.constructor; console.log(instance.name);
Subash

7
@Subash는 캐스팅을 피하는 더 확실한 방법 any입니다.console.log(instance.constructor['name']);
Nick Strupat

1
@Subash 대신 타입 선언을 생성 할 수도 있습니다 : interface Function { name: string; }- "네이티브"정의를 확장합니다.
John Weisz

1
MyClass.name코드를 축소하면 제대로 작동하지 않습니다. 클래스 이름을 축소하기 때문입니다.
AngryHacker

28

나는 파티에 늦었다는 것을 알고 있지만 이것이 효과가 있다는 것을 알았습니다.

var constructorString: string = this.constructor.toString();
var className: string = constructorString.match(/\w+/g)[1]; 

아니면 ...

var className: string = this.constructor.toString().match(/\w+/g)[1];

위의 코드는 전체 생성자 코드를 문자열로 가져오고 정규식을 적용하여 모든 '단어'를 가져옵니다. 첫 번째 단어는 '기능'이어야하고 두 번째 단어는 클래스의 이름이어야합니다.

도움이 되었기를 바랍니다.


4
미안합니다 일반적으로 축소, 못생긴 작업 및 기타 사후 처리 시스템을 사용합니다. 따라서 프로덕션 서버에서는 클래스 이름이 동일하지 않습니다. 그리고 코드가 작동하지 않습니다. 수업 이름을 얻는 좋은 해결책을 찾지 못했습니다. 가장 적합한 방법은 클래스 이름으로 정적 변수를 정의하는 것입니다.
Dima Kurilo

23

내 솔루션은 클래스 이름에 의존하지 않았습니다. object.constructor.name은 이론적으로 작동합니다. 그러나 Ionic과 같은 유형에서 TypeScript를 사용하는 경우 프로덕션으로 이동하자마자 Ionic의 프로덕션 모드가 Javascript 코드를 축소하기 때문에 화염에 빠질 것입니다. 따라서 클래스에는 "a"및 "e"와 같은 이름이 지정됩니다.

내가 한 일은 생성자가 클래스 이름을 할당하는 모든 객체에 typeName 클래스가 있다는 것입니다. 그래서:

export class Person {
id: number;
name: string;
typeName: string;

constructor() {
typeName = "Person";
}

그렇습니다. 실제로 물어 보지 않았습니다. 그러나 잠재적으로 길을 축소 할 수있는 무언가에 constructor.name을 사용하면 두통을 요구합니다.


19

질문을 참조하십시오 .

TypeScript는 JavaScript로 컴파일되므로 런타임시 JavaScript를 실행하므로 동일한 규칙이 적용됩니다.


14

먼저 캐스트에에 인스턴스가 필요 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"

2
TypeScript 2.6.2를 시도했는데이 오류가 발생합니다.Property 'name' does not exist on type 'Function'.
orad

(this as {}).constructor.name(this as object).constructor.name보다 더 나은 any당신이 실제로 GET 자동 완성 :-) 다음 때문에
Simon_Weaver

5

Angular2에서는 구성 요소 이름을 얻는 데 도움이 될 수 있습니다.

    getName() {
        let comp:any = this.constructor;
        return comp.name;
    }

comp : any 는 함수에 초기에 속성 이름이 없으므로 TypeScript 컴파일에서 오류가 발생하기 때문에 필요합니다.


5
그러나이 작동하지 않습니다 만약 당신이 작게하다 / 추하게 코드
Admir Sabanovic

구성 요소의 유용한 '이름'을 얻으려면 tagName을 얻는 것이 좋습니다.- element.nativeElement지시문에서 @Optional() element: ElementRef<HTMLElement>다음 과 같이 구성 요소 이름을 가져 와서 사용할 수 있습니다. if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; }
Simon_Weaver

(및 태그 이름이 축소되지 않음)
Simon_Weaver

4

전체 TypeScript 코드

public getClassName() {
    var funcNameRegex = /function (.{1,})\(/;
    var results  = (funcNameRegex).exec(this["constructor"].toString());
    return (results && results.length > 1) ? results[1] : "";
}

4
타이프 스크립트 / 자바 스크립트 코드를 최소화하고 최적화하면 문제가 발생할 수 있습니다. 함수 이름이 변경되고 클래스 이름 비교가 잘못되었을 수 있습니다.
Antti

4
  • 다음 을 사용 하기 위해 ". prototype. " 을 추가했습니다 myClass.prototype.constructor.name.
  • 그렇지 않으면 다음 코드를 사용 myClass.constructor.name하여 TypeScript 오류가 발생했습니다.

error TS2339: Property 'name' does not exist on type 'Function'.


0

이 솔루션은 축소 축소 후에 작동하지만 메타 데이터로 클래스를 장식해야합니다.

코드 생성을 사용하여 다음과 같은 메타 데이터로 Entity 클래스를 장식합니다.

@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);
}

-2

예상되는 유형을 이미 알고있는 경우 (예 : 메소드가 공용체 유형을 리턴하는 경우 경우 유형 가드를 사용할 수 있습니다.

예를 들어 기본 유형의 경우 typeof guard를 사용할 수 있습니다 .

if (typeof thing === "number") {
  // Do stuff
}

복잡한 유형의 경우 instanceof guard를 사용할 수 있습니다 .

if (thing instanceof Array) {
  // Do stuff
}

귀하의 답변이 질문과 관련이 없기 때문에 추측합니다. 문제는 클래스 이름이 인스턴스 유형에서 조건부로 작업하지 않도록하는 것이 었습니다.
Daniel Leiszen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.