[TS] Interface와 type의 차이점

chaevivi·2023년 9월 25일
2
post-thumbnail

인터페이스(Interface)와 타입 별칭(Type Alias)의 차이점

인터페이스와 타입 별칭은 모두 객체 타입을 정의할 수 있습니다. 객체 타입을 정의할 수 있다는 관점에서는 두 방법의 차이점은 모호합니다. 하지만 여러 다른 관점에서는 차이점이 명확하기 때문에 두 방법을 올바른 곳에 정확히 사용해야 합니다.



1. 인터페이스 (Interface)

인터페이스는 객체 타입을 정의할 때 사용합니다.

인터페이스로 아래의 타입들을 정의할 수 있습니다.

  • 객체의 속성과 속성 타입
  • 함수의 파라미터와 반환 타입
  • 함수의 스펙 (파라미터 개수와 반환값 여부 등)
  • 배열과 객체를 접근하는 방식
  • 클래스

interface Person {
  name: string;
  age: string;
}

function getPerson(someone: Person): Person {
  return someone;
}

위의 코드를 살펴보면,

  • Person 인터페이스에 name과 age 속성의 타입을 정의하였습니다.
  • getPerson() 함수는 someone이라는 파라미터를 받아 그대로 반한합니다.
    • getPerson() 함수의 someone 파라미터는 Person 인터페이스를 타입으로 갖습니다.
    • 따라서 someone 파리미터는 name과 age 속성을 가집니다.
    • getPerson() 함수의 반환값 또한 Person 인터페이스를 타입으로 갖습니다.
    • 따라서 반환값은 name과 age 속성을 가집니다.

1.1. 인터페이스의 상속

인터페이스는 상속으로 타입 정의를 확장할 수 있습니다.


상속이란?

상속은 객체 관 관계를 형성하는 방법이며, 상위(부모) 클래스의 내용을 하위(자식) 클래스가 물려받아 사용하거나 확장하는 기법을 의미합니다.


인터페이스에서 상속받을 때는 extends 키워드를 사용합니다.

interface Person {
  name: string;
  age: string;
}

interface Developer extends Person {
  skill: string;
}

const dove: Developer = {
  name: '도브',
  age: 20,
  skill: 'TypeScript'
};

위의 코드를 살펴보면,

  • Person 인터페이스를 선언하였습니다. Developer 인터페이스는 Person 인터페이스를 상속받았습니다.
  • Developer 인터페이스는 Person 인터페이스를 상속 받았기 때문에 Person의 속성인 name과 age 속성을 모두 사용할 수 있습니다.
  • 따라서 dove 변수는 Developer 인터페이스 타입을 사용하기 때문에 name, age, skill 속성을 모두 사용할 수 있습니다.


2. 타입 별칭 (Type Alias)

타입 별칭은 특정 타입이나 인터페이스 등을 참조할 수 있는 타입 변수를 의미합니다.

  • 타입에 의미를 부여해서 별도의 이름으로 부르는 것입니다.
  • 해당 타입이 어떤 역할을 하는지 이름을 짓고 싶을 때 사용하기도 합니다.
  • 반복되는 타입을 변수화해서 쉽게 표기하고 싶을 때도 사용합니다.

type MyMessage = string | number;

function logText(text: MyMessage) {
  // ...
}

const message: MyMessage = '안녕하세요';

위의 코드를 살펴보면,

  • string | number 유니언 타입을 MyMessage라는 타입 별칭으로 정의하였습니다.
  • logText() 함수와 message 변수에 MyMessage 타입으로 지정합니다.
  • 유니언 타입을 타입 별칭으로 지정했기 때문에 번거롭게 유니언 타입을 반복해서 지정하지 않아도 됩니다.


3. 인터페이스와 타입 별칭의 차이점

인터페이스와 타입 별칭은 매우 비슷하기 때문에, 많은 경우에 두 방법을 자유롭게 선택해서 사용할 수 있습니다. 그리고 인터페이스의 대부분의 특징들을 타입 별칭에서도 사용 가능합니다. 예를 들어, 인터페이스와 타입 별칭은 모두 객체 타입을 정의할 수 있습니다.

interface User {
  id: string;
  name: string;
}


type User = {
  id: string;
  name: string;
}

그렇다면 어떤 부분에서 두 방법에 차이점이 존재할까요?


3.1. 확장 가능성

가장 큰 특징은 확장 가능성입니다.
타입 별칭은 새 속성을 추가하기 위해 다시 열 수 없지만, 인터페이스는 항상 확장 가능합니다. 다시 말해, 타입 별칭은 확장이 불가능하고, 인터페이스는 확장이 가능합니다.


예시를 통해 더 자세히 알아보겠습니다.


(1) 확장

  • 인터페이스 확장

    interface Animal {
      name: string;
    }
    
    interface Bear extends Animal {
      honey: boolean;
    }
    
    const bear = getBear();
    bear.name;
    bear.honey;
    • Animal 인터페이스를 선언하였습니다.
    • Bear 인터페이스는 Animal 인터페이스를 상속 받았기 때문에 Animal의 name 속성을 사용할 수 있습니다.
    • Bear 인터페이스는 extends 키워드로 Animal 인터페이스를 상속 받아 확장하였습니다.
  • 인터섹션 타입으로 타입 확장

    type Animal = {
      name: string;
    }
    
    type Bear = Animal & { 
      honey: boolean;
    }
    
    const bear = getBear();
    bear.name;
    bear.honey;
    • Animal 타입을 선언하였습니다.
    • Bear 타입은 Animal의 name 속성을 사용하기 위해 인터섹션 타입(&)을 사용하였습니다.
    • Bear 타입은 & 인터섹션 타입으로 Animal 타입과 합쳐서 사용할 수 있습니다.

(2) 이름 중복 사용

  • 인터페이스 이름 중복 사용

    interface Window {
      title: string;
    }
    
    interface Window {
      ts: TypeScriptAPI;
    }
    
    const src = 'const a = "Hello World"';
    window.ts.transpileModule(src, {});
    • title과 ts 속성을 가진 각각의 Window 인터페이스를 선언하였습니다.
    • 인터페이스는 이름을 중복으로 선언하면 인터페이스 내용을 합치는 특성이 있습니다. 이를 선언 병합(declaration merging) 이라고 합니다.
    • 따라서 Window 인터페이스를 사용하는 변수나 함수는 title과 ts 속성을 모두 사용할 수 있습니다.
  • 타입 이름 중복 사용

    type Window = {
      title: string;
    }
    
    type Window = {
      ts: TypeScriptAPI;
    }
    
     // Error: Duplicate identifier 'Window'.
    • title과 ts 속성을 가진 Window 타입을 선언하였습니다.
    • 타입 별칭은 이름을 중복으로 사용할 수 없습니다.


3.2. 사용할 수 있는 타입의 차이

인터페이스와 타입 별칭은 서로 사용할 수 있는 타입에 차이가 있습니다.
인터페이스는 주로 객체 타입을 정의하는데 사용하고, 타입 별칭은 중복된 타입 코드를 줄이고 주요 데이터 타입이나 인터섹션 타입, 유니언 타입 등을 정의하는데 사용합니다.


// 데이터 타입
type ID = string;
// 인터섹션 타입
type Teacher = Person & Adult;
// 유니언 타입
type Product = Tshitr | Shoes;

// 유틸리티 타입
type Admin = { name: string; age: number; role: string; }
type OnlyName = Pick<Admin, 'name'>

// 맵드 타입
type Picker<T, K extends keyof T> = {
  [P in K]: T[P];
};

위의 타입들은 타입 별칭에서는 사용할 수 있지만 인터페이스에서는 사용할 수 없습니다.



4. 정리

특징인터페이스 Interface타입 별칭 type
타입 확장가능 -> extends 키워드 사용불가능 -> 대신 & 인터섹션 타입 사용
이름 중복 사용가능 -> 선언 병합불가능
사용 가능한 타입객체객체, 다른 주요 데이터 타입, 인터섹션 타입, 유니언 타입, 유틸리티 타입, 맵드 타입



출처

📖 쉽게 시작하는 타입스크립트
🔗 https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#interfaces

profile
직접 만드는 게 좋은 프론트엔드 개발자

0개의 댓글