Language/Javascript

Typescript - type alias vs interface 방식 비교

둉이 2022. 2. 2. 18:47

타입스크립트에서 타입을 선언하는 방식에는 type 키워드를 사용한 type alias 방식과 interface 키워드를 사용한 방식 2가지가 있다.

 

 

Type Alias

type Point = {
  x: number;
  y: number;
};

type SetPoint = (x: number, y: number) => void;

 

Interface

interface Point {
  x: number;
  y: number;
}

interface SetPoint {
  (x: number, y: number): void;
}

 

 

둘의 차이점은 다음과 같다.

 

1. interface는 동일한 이름으로 재선언 가능

interface에서는 동일한 이름을 갖는 인터페이스를 중복하여 선언할 수 있다.

 

이를 선언 병합(Declaration merging)이라고 한다.

 

따라서, interface로 선언된 타입은 선언 이후의 타입 확장에도 용이하다.

 

interface 재선언

 

타입 alias는 동일한 이름의 타입을 선언하면 에러가 발생한다.

 

선언 이후에는 해당 타입의 내용을 변경할 수 없음을 의미한다.

 

type 재선언 -> Error!

 

2. interface는 extends 키워드를 사용하여 확장된 타입 선언 가능

인터페이스는 extends 키워드를 사용하여 명시적으로 기존 타입의 확장이 가능하다.

 

그럼 type alias로 선언된 타입은 extends 키워드를 사용한 확장이 불가능하다는 것일까?

 

아니다. 물론 type alias로 선언된 타입도 extends 키워드를 적용하여 타입 확장이 가능하다.

 

다만 type alias로 선언된 타입에 extends 키워드를 적용하여 새로운 type alias 타입을 선언하는 것은 불가능하다. 

type TPoint = {
  x: number;
  y: number;
};

interface IPoint {
  x: number;
  y: number;
}

interface NewPoint extends TPoint {  // 가능
  z: number;
}

interface NewPoint2 extends IPoint {
  z: number;
}

const p: NewPoint = {
  x: 1,
  y: 2,
  z: -3,
};

 

 

그리고 type alias으로 선언된 타입은 intersection 키워드인 &을 사용하는 방식으로도 타입 확장이 가능하다.

(자세한 내용은 3번 참고!)

 

참고로 type alias와 인터페이스 방식 둘 다, 클래스를 선언할 때 implements 키워드를 사용하여 인터페이스를 구현할 수 있다.

type TUserImpl = {
  name: string;
  age: number;
  sayHi: (name: string) => void;
};

interface IUserImpl {
  name: string;
  age: number;
  sayHi: (name: string) => void;
};

// 둘 다 가능
class User implements TUserImpl {
// class User implements IUserImpl {
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  sayHi(name: string): void {
    console.log(`Hello, ${name}!`);
  }
}

 

3. type alias 방식에서는 intersection(&), union(|) 키워드와 tuple 사용 가능

type alias 방식에서는 타입을 선언할 때 intersection(&)과 union(|) 연산자 사용이 가능하다.

(인터페이스 선언 방식에서는 사용 불가)

 

그리고 튜플 형태의 타입도 선언할 수 있다.

type PartialPointX = { x: number };
type PartialPointY = { y: number };

// intersection
type IntersectionPoint = PartialPointX & PartialPointY;

// union
type UnionPoint = PartialPointX | PartialPointY;

// tuple
type Data = [number, string];

 

 

여기서 주의해야 할 점이 있다.

 

union 연산자를 사용한 타입의 경우에는 extends, implements 키워드 사용이 불가능하다.

 

union 연산자를 사용하여 만든 type은 extends 키워드로 확장 불가

 

4. type alias는 VSCode 상에서 프리뷰 기능을 통해 해당 타입 내의 속성 정보 조회 가능

VSCode에서 타입을 지정한 부분에 마우스 오버를 하면 해당 타입에 대한 툴팁을 조회할 수 있다.

 

이 때, type alias로 선언된 타입의 경우에는 해당 타입의 전체 속성 정보를 조회할 수 있다.

 

interface 키워드로 선언된 타입의 경우에는 인터페이스명만 조회된다.

 

interface vs type

 

 

그럼 두 방식 중에 무엇을 사용하는 게 좋을까?

 

Typescript 공식 문서에서는 type alias 대신 interface 키워드를 사용하여 타입을 선언할 것을 권장하고 있다.

 

따라서, 튜플이나 &, | 연산자를 필수적으로 사용해야 하는 상황이 아니라면 interface 키워드를 사용하는 것이 바람직하다.

 

 

참고 자료

 

Interfaces vs Types in TypeScript

What is the difference between these statements (interface vs type) in TypeScript? interface X { a: number b: string } type X = { a: number b: string };

stackoverflow.com

 

Type vs Interface, 언제 어떻게?

TypeScript에서 Type Alias와 Interface의 차이를 알아보기

medium.com