원래 JavaScript는 클래스와 그 생성자에 대한 엄격한 타입을 지원하지 않아 런타임 오류를 초래했었습니다. TypeScript는 더 안전한 프로그래밍을 위해 타입 시스템을 추가하고 상속을 지원하는 생성자의 타입화를 도입했습니다. 이는 대규모 애플리케이션 개발에 중요합니다.
TypeScript에서 생성자의 타입화는 생성자 시그니처, 생성되는 인스턴스의 타입 및 상속의 특징을 동시에 고려해야 합니다. 기본 클래스와 파생 클래스의 생성자 시그니처가 일치하지 않거나, 생성자의 입력 매개변수가 아닌 반환값만 타입화된 경우 문제가 발생합니다.
TypeScript에서는 특별한 시그니처를 통해 생성자를 명시적으로 타입화할 수 있으며, new (...args: any[]) => T 표현식을 사용합니다. 상속할 때는 시그니처의 일관성을 유지하고 기본 클래스를 올바르게 확장하는 것이 중요합니다.
코드 예:
class Animal { constructor(public name: string) {} } class Dog extends Animal { constructor(name: string, public breed: string) { super(name); } } // 생성자 타입 function createInstance<T>(C: new (...args: any[]) => T, ...args: any[]): T { return new C(...args); } const dog = createInstance(Dog, 'Rex', 'Labrador');
주요 특징:
new로 선언되는 별개의 엔티티입니다.Java나 C#처럼 클래스에 여러 개의 생성자를 선언할 수 있나요?
아니요, TypeScript는 여러 생성자를 지원하지 않습니다. 오버로드 시그니처로 오버로딩을 구현해야 하며, 한 개의 구현을 사용하는 올바른 접근 방식은 다음과 같습니다:
class Example { constructor(x: string); constructor(x: number); constructor(x: number | string) { // 하나의 구현 } }
매개변수를 무시하고 생성자의 반환 타입만 타입화할 수 있나요?
아니요, 생성자 시그니처는 반드시 매개변수를 포함해야 합니다. 올바른 타입화 예:
interface Constructable<T> { new (...args: any[]): T; }
서브클래스에서 super 호출 없이 생성자를 선언하면 어떻게 되나요?
컴파일 오류가 발생합니다: 서브클래스의 생성자는 this에 접근하기 전에 super를 호출해야 합니다.
프로젝트에서 기본 클래스 Animal을 생성자(name)와 함께 사용했으나, 상속받은 Dog에서 (name, breed)를 추가하고 시그니처를 올바르게 확장하는 것을 잊었습니다.
장점:
단점:
생성자 타입이 별도로 분리되어 있고, 팩토리 createInstance가 CorrectConstructable<T>를 통해 매개변수화되었으며, 시그니처가 준수되었습니다.
장점:
단점: