타입스크립트에서 클래스의 타입을 표현하기

joonseokhu·2022년 5월 5일
3
post-thumbnail
post-custom-banner

타입스크립트에서 클래스는 값이면서 동시에 타입으로 쓰일 수 있다.

class User {
  constructor(
    public name: string,
    public age: number,
  ) {}
}

이렇게 만든 User 클래스는 user 인스턴스 객체에 대한 타입이 필요할때 사용할 수 있다.

const sayHello = (user: User) => 
  `안녕 나는 ${user.name}이고 나이는 ${user.age}살 이야`

const kcs = new User('김철수', 149);

sayHello(kcs);
// 안녕 나는 김철수이고 149살 이야

sayHello({ name: '김칠수', weight: 240 });
// Argument of type '{ name: string; weight: number; }' is not assignable to parameter of type 'User'

sayHello 함수는 파라미터 user의 타입으로 User 클래스가 선언되어있다. 파라미터 user 에는 User 클래스의 인스턴스 (또는 같은 타입의 프로퍼티들이 똑같이 들어있는 객체) 만 사용할수 있다.

그런데 어떨때는, 함수의 파라미터가 클래스의 인스턴스가 아니라, 클래스 그 자체여야 할 때도 있다.

const createInstance = (ClassToCreate: ??, args: ??) =>
  new ClassToCreate(...args);

이럴때 클래스 그 자체를 묘사하는 타입을 어떻게 만들어야 할까?

ClassType

/**
 * @see https://stackoverflow.com/questions/39392853/is-there-a-type-for-class-in-typescript-and-does-any-include-it
 */
export interface ClassType<T, A extends any[] = any[]> extends Function { new(...args: A): T; }

이걸 쓰자.

stackoverflow 에 있는 여러 답변들을 조합해서 쓰기 좋게 만들었다.

사용방법 1 - 직접 클래스 타입 만들기

class Foo {
  private c: boolean
  constructor(public a: string, b: number) {
    this.c = !b;
  }
}

/**
 * 첫번째 인자에 클래스를 넣고,
 * 두번째 인자에 그 클래스의 생성자가 받는 파라미터의 타입을 튜플 타입으로 넣어준다.
 * 파라미터 타입이 자동으로 추론 되지 않다보니 다소 불편하긴 하다.
 */
type FooClass = ClassType<Foo, [string, number]>;

const MyFooClass: FooClass = Foo;

// MyFooClass 의 인스턴스가 Foo 와 같기때문에 타입에러가 나지 않는다.
const foo: Foo = new MyFooClass('def', 5678);

사용법 2 - 함수 파라미터의 타입으로 사용하기

/**
 * 함수의 제네릭으로 ClassType의 제네릭과 같은 제네릭을 선언해주고,
 * 함수의 첫번째 파라미터로 ClassType을 선언한다.
 * 생성자 파라미터 `A` 는 함수 안에서 자동으로 추론 된다.
 */
const createInstance = <T, A extends any[]>(
  classToCreate: ClassType<T, A>,
  constructorArgs: A,
) => {
  return new classToCreate(...constructorArgs);
}

class Foo {
  private c: boolean
  constructor(public a: string, b: number) {
    this.c = !b
  }
}

// 아주 잘 작동한다.
const foo: Foo = createInstance(Foo, ['abc', 1234]);

함수 자체를 타입으로 사용해야 할 때에는 보통 함수의 파라미터로 받는 상황일 때 일 것이다. 다행히도 함수에서 우리가 만든 ClassType 을 쓸때는 생성자 파라미터에 대해 자동추론을 사용할 수 있다.

profile
풀스택 집요정
post-custom-banner

0개의 댓글