타입스크립트를 공부하면서 Type Alias와 Interface의 차이점이 궁금해졌다. 언뜻보면 두 개는 같은 역할을 하고 있는데 어떤 차이가 있을까?
아래는 타입스크립트 공식 문서에 나와있는 Type Alias의 설명이다.
지금까지 object 타입과 union 타입을 사용할 때 직접 해당 타입을 표기하여 사용했다. 이것은 편리한 방법이었다.
// 이전에는 아래와 같이 타입을 지정했다. const a: string = "hello";
하지만 똑같은 타입을 한 번 이상 재사용하거나 하나의 이름으로 참조하고 싶은 경우도 존재한다. Type Alias는 이러한 경우에 사용이 가능하다.
type Point = { x: number; y: number; }; // Exactly the same as the earlier example function printCoord(pt: Point) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); } printCoord({ x: 100, y: 100 });
Type Alias를 사용하면 object 타입 뿐만 아니라 모든 타입에 대해 새로운 이름을 부여할 수 있다. 즉, union type에도 Type Alias를 사용할 수 있는 것이다.
type ID = number | string
위와 같이 Type Alias를 사용하면 타입 재사용성이 쉬워지며 내가 원하는 이름으로 참조할 수 있게 된다. 그러면 Interface는 어떤 역할을 할까? 다시 공식문서를 살펴보자.
Interface는 object 타입을 만드는 또 다른 방법이다.
interface Point { x: number; y: number; } function printCoord(pt: Point) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); } printCoord({ x: 100, y: 100 });
Type Alias를 사용하는 경우와 마찬가지로 위 코드는 객체의 타입을 선언해서 사용할 수 있다.
Type Alias는 모든 타입에 이름을 부여할 수 있지만, Interface는 object 타입에만 이름을 부여할 수 있다.
그렇다면 의문점이 생긴다. Interface가 할 수 있는 모든 일을 Type Alias가 가능한데, 왜 Interface를 없애지 않고 사용하는 것일까?
하지만 Type Alias와 Interface는 서로 다른 성격을 가지고 있다.
1. Type Alias와 Interface는 모두 확장이 가능하지만 Type Alias로 만들어진 타입은 extend
와 implements
를 사용할 수 없다.
interface UserInterface {
name: string
age: number
}
type UserTypeAlias = {
name: string
age: number
}
// extends
interface UserInterface2 extends UserInterface {
region: string
}
//Error (UserTypeAlias'은(는) 형식만 참조하지만, 여기서는 값으로 사용되고 있습니다.)
type UserTypeAlias2 extends UserTypeAlias {
region: string
}
그렇기 때문에 Type Alias를 확장시키기 위해서 &
을 사용해야 한다.
type UserTypeAlias2 = UserTypeAlias & {
region: string
}
2. Interface는 재선언을 함으로써 확장이 가능하지만, Type Alias는 재선언이 불가하다.
// Interface 확장
interface PostType {
title: string;
}
interface PostType {
content: string;
}
const post: PostType = {
title: "Hello",
content: "world",
}
// Error ('PostType' 식별자가 중복되었습니다.)
type PostType = {
title: string;
}
type PostType = {
content: string;
}
const post: PostType = {
title: "Hello",
content: "world"
}
3. Turple을 사용해야 할 때는 Interface보다 Type Alias가 훨씬 편리하다.
// Interface
interface A {
0: NumberTuple
1: StringTuple
length: 2
}
// Type Alias
type NumberTuple = [number, number]
type StringTuple = [string, string]
type A = [NumberTuple, StringTuple, ...string[]]
한 눈에 보기에도 Type Alias가 더 편리하지 않은가? 위와 같은 상황에서는 Type Alias를 활용해야하는 것이 좋은 것 같다.
이렇게 Type Alias와 Interface의 차이점에 대해 알아봤다. 지금까지 프로젝트를 진행하면서 대부분의 상황에서 Type Alias를 사용하며 Interface의 필요성에 대해 느끼지 못하고 있었다. 하지만 이렇게 두 개의 차이점에 대해 분석하고 찾아보면서, Type Alias보다는 Interface가 확장성면에서도 훨씬 뛰어나고 여러 부분에서 쓸 수 있겠다라는 생각이 들었다. 실제로 공식 문서에서도 Type Alias보다는 Interface의 사용을 권장하고 있다. 그 이유에 대해 생각해봤을 때,
- extends 키워드를 통한 확장성이 편리하다.
- 선언 병합을 통해 타입 설정의 오류가 최소화 될 수 있다.
이 두가지 이유 모두 프로젝트를 개인으로 진행하는 것이 아닌 팀으로 진행하는 경우가 많은 개발 분야에서 Type Alias보다 장점이 되는 부분인 것이었다. 그렇다고 Type Alias를 유기하고 Interface를 쓸 필요는 없다고 생각한다. 두 개의 장점을 적절히 활용하며, 적재적소에 사용할 수 있도록 공부하며 연습하자.
참고
1. https://vallista.kr/TypeScript%EC%9D%98-interface%EC%99%80-type-alias/
2. https://radlohead.gitbook.io/typescript-deep-dive/type-system/interfaces1
3. https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#interfaces
4. https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases