Type aliases VS Interface

GI JUNG·2022년 10월 1일
1

typescript

목록 보기
1/10
post-thumbnail

typescript를 공부하면서 type을 정의하는데 있어서 Type aliasInterface가 있는데 공통된 일을 처리하는 것이 왜 2개나 필요한가 생각들다보니 둘 사이의 차이점이 궁금했다. 찾고 공부하면서 느낀 것은 둘 사이의 명확한 차이를 제외하고 컨벤션이나 개인의 스타일에 맞게 사용하면 될 것 같다.

일단 내가 공부한 것으로부터 결론부터 내자면 아래와 같다.

  1. 객체를 정의하는 것은 interface를 주로 사용하고 primitives, unions, tuple은 type alias로 정의한다.
  2. 타입 추가 또는 확장에 있어서 interface는 열려있고 type alias는 닫혀있다.
  3. 선언병합의 편리성을 위해 외부에 공개하는 API같은 경우에는 interface로 구현하기.
  4. 에러가 발생 시 interface가 type alias보다 보다 더 간결하고 요점을 메세지로 보여준다.(아래 typescript playground 참고)

TypeScript can provide terser and more focused messages when working with interfaces

  1. primitive, union, tuple 타입을 정의하는 것을 제외하고는 interface 사용을 지향하자.
  2. type alias를 intersection을 통해서 하면 상관없지만 union을 통해서 선언하면 class implements에는 에러가 발생한다.

위에서 결론 내린 것에서 중요하다고 생각되는 부분들을 위주로 정리했다.

Type alias와 Interface 선언

기본적으로 interfacetype alias는 type을 정의하는데 있어서 사용되며 extends, implements 등 공통적으로 가능한 것이 많다.

Interface

interface Person {
    name: string;
    age: number
}  
interface PrintPersonInfo {
    (name: string, age: number): void	
}

Type alias

type Person = {
    name: string;
    age: number
}

type PrintPersonInfo = (name: string, age: number) => void;

primitive, union, tuple

typescript 팀이 권장하는 방식은 union, tuple 타입을 정의하는 것을 제외하고는 interface 사용을 지향하라고 한다. 그리고 interface객체의 구조를 설명하는데 사용하라고 추천한다.

아래 코드는 primitive, union, tuple을 type alias로 정의한 것이다.

// primitive type
type InputNumber = number;
type InputString = string;

// union type
type Input = inputNumber | inputString;

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

Declaration Merge(선언 병합)

interface는 open되어 있고 type alias는 close되어 있다고 typescript doc에서 말한다. 이는 둘 사이의 가장 큰 차이점이라 생각되며, 뜻만 보면 이해하기 어렵지만 아래의 예시를 참고하면 이해가 쉽다.

// from typescript doc
One major difference between type aliases vs interfaces are that interfaces are open and type aliases are closed.

Interface

interface Person {
	name: string
}

interface Person {
	age: number
}

interface는 몇 번의 선언을 통해 type을 확장시킬 수가 있다.

Type alias

type Person = {
	name: string;
}

// error occurred!! 
type Person = {
	age: number
}

type alias는 interface와 달리 선언하는 위치해서 해주어야 한다.

type Person = {
	name: string;
  	age: number;
}

📒 type 병합을 interface는 외부에서 가능해 open이란 개념을 도입하고 type alias는 외부에서 확장이 불가능해 close라고 함을 알 수 있다.

Implements

interface PersonInterface {
  height: number;
  age: number;
}

type PersonType = { height: number } | { age: number };

class Male implements PersonInterface {
  height = 178;
  age = 22;
}

// ❌ error occur!!
class Female implements PersonType {
  height = 166;
  age = 21;
}

📒 type alias를 union type으로 지정하면 class가 implements하는데 오류가 난다. 이는 class나 interface는 static blueprint로서 고려되기 때문이다.

하지만, 아래와 같이 intersection type으로 type alias를 선언하는 것은 문제가 없다.

type PersonType = { name: string } & { age: number };

// ⭕️ name과 age를 구현해야된다는 점에서 static blueprint의 조건을 충족한다.
class Person implements PersonType {
  name =  'luna';
  age = 21
}

정리

위에서 정리한 것에 따라 특정한 상황을 제외하고는 interface를 위주로 사용할 생각이며 가능한 typescript 팀에서 지향하는 방향으로 작성할 생각이다. 또한 공동으로 프로젝트를 할 때도 interface가 유리하다는 생각을 한다. 또한 interface로 구현시 오류의 원인을 보다 정확하게 파악할 수 있기 때문이다.


참고

typescript playground

typescript doc

stackoverflow

휴먼스케이프 tech blog

profile
step by step

0개의 댓글