TypeScript - interface vs type alias

치맨·2024년 2월 13일
0

TypeScript

목록 보기
4/4
post-thumbnail

타입스크립트를 하면서 많은 궁금증 중 하나가 언제 interface를 사용하고, 언제 type alias를 사용해야 하는지입니다.

그냥 취향 차이인가? 그냥 팀 컨벤션에 따라가는 건가? 아직 공부만 하는 취준생이라 정확히는 모르겠지만, 최소한 이 둘의 차이 정도는 알고 있어야 할 것 같아서 정리를 해보려고 합니다.

여러 강의나 유투브를 통해 다른분들의 경우 아래와 같이 사용한다고 합니다.
그래서 저는 팀 프로젝트나, 회사 컨벤션에 따라가겠지만 개인프로젝트의 경우 저는 3번의 경우로 사용하려고 하고 있습니다.

1. interface만 사용한다.
2. type alias만 사용한다.
3. 객체의 구조를 나타내는 경우는 interface, 기존의 타입을 재사용하여 새로운 타입을 생성할 때 type alias를 사용 

목차

interface 와 type alias

type alias

  • 공식문서에 따르면 아래와 같습니다.

    You can actually use a type alias to give a name to any type at all, not just an object type. For example, a type alias can name a union type

  • 즉 객체 타입뿐이 아닌 모든 타입에 대하여 새로운 이름을 부여할 때 사용하나 봅니다.

type ID = number | string;

type Sushi = {
    calories:number;
    salty:boolean;
    tasty:boolean
}

interface

  • 공식문서에 따르면 아래와 같습니다.

    An interface declaration is another way to name an object type:

  • 즉 객체 타입을 정의할 때 사용하나 봅니다.


interface Sushii  {
  calories: number;
  salty: boolean;
  tasty: boolean;
};

interface 와 type alias 차이점

  1. 위에서 나타나지만, type alias는 객체타입 뿐 아니라 모든 타입에 사용할 수 있지만, interface의 경우 객체 타입만 사용 가능합니다.
  type ID = number | string;

  type Sushi = {
      calories:number;
      salty:boolean;
      tasty:boolean
  }
  -----------------

  interface Sushii  {
    calories: number;
    salty: boolean;
    tasty: boolean;
  };
  1. 인터페이스의 경우 이름과 범위가 같은 인터페이스가 여러 개 있다면 이들을 자동으로 합쳐지지만(선언 합침), 타입별칭의 경우 에러가 발생한다.
// 인터페이스
interface User{
    name:string
}

interface User {
  age: number;
}

let user : User ={
    name:'chiman',
    age:3
}
-----------------
// 타입별칭

type User = {   // 식별자가 중복되었습니다.
  name: string;
}

type User2 = {    // 식별자가 중복되었습니다.
  age: number;
}
  • 인터페이스의 이름이 같을 경우 한 타입의 프로퍼티와 다른 타입의 프로퍼티가 동일하지 않다면 에러가 발생한다.
  • 제네릭을 선언한 인터페이스의 경우 제네릭들의 선언 방법과 이름까지 똑같아야 합칠 수 있다.
interface User {
  name: string;
}

interface User {
  name: number;     // 에러 발생 : name속성은 string 타입이어야함
  age: number;
}

let user: User = {
  name: 'chiman',
  age: 3,
};

---------
// 제네릭
interface User<Age extends number> {
  age:Age
}

interface User<Age extends string> {   // User의 모든 선언에는 동일한 형식 매개 변수가 있어야 합니다.
  age: Age;
}
  1. 다른 타입과 조합하는 경우 타입별칭은 (&)연산자를 사용하지만, 인터페이스는 extends를 사용한다.
// 인터페이스

interface Food {
  calories: number;
  salty: boolean;
  tasty: boolean;
};

interface Sushi extends Food {
  salty: boolean;
};

interface Cake extends Food {
  sweet: boolean;
};

------------------------------

// 타입별칭
type Food = {
  calories: number;
  salty: boolean;
  tasty: boolean;
}

type Sushi = Food & {
    salty: boolean;
}

type Cake = Food & {
    sweet: boolean;
}
  1. 타입별칭은 타입 별칭의 오른쪽편에 타입 표현식(타입, &, | 등 타입연산자)를 포함한 모든 타입이 등장할 수 있다. 반면에 인터페이스의 오른편에는 반드시 형태(객체의 구조)가 나와야 한다.
// 인터페이스(Interface)
interface MyInterface {
    prop1: string;
    prop2: number;
}

// 타입 별칭(Type Alias)
type MyTypeAlias = number | string;
  1. 인터페이스를 상속할 때 타입스크립트는 상속받는 인터페이스 타입에 상위 인터페이스를 할당할 수 있는지 확인한다.
interface A {
  good(x: number): string;
  bad(x: number): string;
}

interface B extends A {
  good(x: number | string): string;
  bad(x: string): string; // 에러 발생 number 타입은 string에 할당할 수 없음
}
  • 그러나 타입별칭으로 바꾸면 타입스크립트는 확장하는 타입을 최대한 조합하는 방향으로 동작하기에 에러가 발생하지 않는다.
type A =  {
  good(x: number): string;
  bad(x: number): string;
}

type B = A &   {
  good(x: number | string): string;
  bad(x: string): string;
}

참고

profile
기본기가 탄탄한 개발자가 되자!

0개의 댓글