2024년 2월 27일 작성

TypeScript Type Alias - Type 별칭

TypeScript의 Type Alias는 기존 type에 새로운 이름을 부여하여, 복잡한 type 구조를 간결하게 표현하고 가독성을 높일 수 있는 기능입니다.

Type Alias : Type에 이름 붙이기

  • type alias는 기존에 존재하는 하나 이상의 type에 새로운 이름을 부여하는, TypeScript의 강력한 type system을 활용한 기능 중 하나입니다.
    • 복잡한 type 구조를 간결하게 표현하고, code의 가독성을 높일 수 있습니다.
  • type alias는 type keyword를 사용하여 정의합니다.
type Person = {
    name: string,
    age?: number
}

Type Alias의 특징

  1. 재사용성 : type alias를 통해 정의한 type은 project 전반에 걸쳐 재사용할 수 있어, type 관리를 용이하게 합니다.

  2. 가독성 향상 : 복잡한 type을 간결하고 의미 있는 이름으로 정의할 수 있어, code의 가독성이 향상됩니다.

  3. 확장성 제한 : type alias는 확장이 불가능하며, 상속이나 interface처럼 기존 type을 확장하여 새로운 type을 만들 수 없습니다.

    • 대신, intersection type을 사용하여 type을 결합할 수는 있습니다.

Type Alias 사용하기

Primitive Type Alias

  • 간단한 예로, 문자열이나 숫자 같은 기본 type에 더 구체적인 이름을 부여할 수 있습니다.
type UserID = number;
type UserName = string;

type Str = 'Lee';    // string literal type

let id: UserID = 2;
let nm: UserName = 'simin';

id = '2';    // Error: Type 'string' is not assignable to type 'number'.

Union Type Alias

  • 두 개 이상의 type을 하나로 결합한 type을 정의할 때 사용합니다.
  • union type을 통해 변수가 여러 type 중 하나를 가질 수 있음을 명시할 수 있습니다.
type StringOrNumber = string | number;    // primitive union type
type Func = (() => string) | (() => void);    // function union type
type Shape = Square | Rectangle  Circle;    // interface union type

type Name = 'Lee' | 'Kim';    // string literal union type
type Num = 1 | 2 | 3 | 4 | 5;    // number literal union type
type Obj = {a: 1} | {b: 2};    // object literal union type

Tuple Type Alias

  • 고정된 길이의 배열 type을 정의할 때 사용하며, 각 요소의 type을 정확히 지정할 수 있습니다.
type Point = [number, number];
type Tuple = [string, boolean];

const tupleA: Tuple = ['', true];    // OK
const tupleB: Tuple = ['', ''];    // Error

Object Type Alias

  • 객체의 구조를 정의할 때 사용합니다.
  • interface와 유사하지만, type alias를 사용하면 객체 type뿐만 아니라 다른 type들과의 조합도 가능합니다.
type Point = {
    x: number;
    y: number;
};
type UserID = number;
type UserName = string;

type User = {
    id: UserID;    // type alias를 type으로 지정
    name: UserName;    // type alias를 type으로 지정
    age: number;
};

Intersection Type Alias

  • 두 개 이상의 type을 모두 만족하는 새로운 type을 생성할 때 사용합니다.
  • 이를 통해 여러 type의 특성을 합칠 수 있습니다.
type Circle = {
    radius: number;
};

type Colorful = {
    color: string;
};

type ColorfulCircle = Circle & Colorful;

비슷하지만 다른 Type Alias와 Interface

  • type alias와 interface 모두 custom type을 정의하고, 정의한 custom type을 type으로 사용할 수 있습니다.
// 작성 : type alias
type Person = {
    name: string,
    age?: number
}

// 작성 : interface
interface Person {
    name: string,
    age?: number
}
// 사용 : type alias, interface 공통
const person = {} as Person;    // 빈 객체를 'Person' type으로 지정
person.name = 'Lee';
person.age = 20;
person.address = 'Seoul';    // Error
  • 작성과 사용 방법이 비슷하지만, 몇 가지 주요한 차이점이 있습니다.
기능 / 특징 Type Alias Interface
정의 방식 type keyword를 사용하여 정의함. interface keyword를 사용하여 정의함.
확장 가능성 확장 불가능. 새로운 type(intersection type)을 생성하여 확장해야 함. 확장 가능. extends를 사용하거나 같은 이름으로 추가 선언하여 확장할 수 있음.
재정의 및 병합 재정의 불가능. 동일 이름으로 여러 번 선언할 수 없음. 자동 병합 지원. 동일 이름의 interface를 여러 번 선언하면 자동으로 병합됨.
Union/Intersection Type 지원함. union type과 intersection type 사용 가능. 직접적으로 지원하지 않음. interface를 확장하여 유사한 기능 구현 가능.
Type 결합 복잡한 type 결합에 유리함. 다양한 type을 결합한 새로운 type 정의 가능. 주로 상속을 통한 확장에 유리함. 단일 상속 구조를 따름.
  • 대부분의 경우, type alias와 interface는 개인적인 선호에 따라 선택하여 사용할 수 있습니다.
    • 많은 개발자들이 함수형 programming paradigm과 잘 맞기 때문에 type alias를 선호합니다.
      • type alias의 풍부한 type 표현을 사용하여, type-safe한 방식으로 함수형 programming 기능(함수형 구성, 불변성 등)을 쉽게 충족시킬 수 있습니다.
  • interface와 type alias 둘 중 하나를 반드시 사용해야 하거나, 사용하는 편이 더 나은 경우도 있습니다.

Interface를 사용해야 할 때

  • interface가 가지고 있는 대부분의 기능은 type alias로도 사용할 수 있지만, 예외적으로 interface의 ‘선언 병합(declaration merging)’은 type alias에서 사용할 수 없습니다.
  • 따라서 기존의 library를 확장하거나 새로운 type의 spec을 작성할 때, 선언 병합이 필요다면 interface를 사용해야 합니다.
    • interface의 선언 병합은 type alias에서 intersection type을 사용하여 비슷하게 구현할 수도 있습니다.
  • 또한, program에 OOP의 상속 개념을 적용하는 경우, interface의 extends keyword를 사용하는 것이 type alias들을 intersection type으로 만들어 사용하는 것보다 더 낫습니다.

Type Alias를 사용해야 할 때

  1. 원시 type에 새로운 이름(별칭)을 생성할 때.
  2. union type, tuple type, function type, 또는 더 복잡한 type을 정의할 때.
  3. 함수를 overloading할 때.
  4. mapped type, 조건부(conditional) type, type guard, 또는 기타 고급(advanced) type 기능을 사용할 때.
  • interface로는 구현하기 어려운 type alias만의 고급 기능들이 있습니다.
    • 예를 들어, 조건부(conditional) type, generic type, type guard, 고급(advanced) type 등.
    • type alias의 고급 기능을 사용하여, 강력한 type system을 갖춘 application을 만들 수 있습니다.

Type Alias 고급 기능 사용 예제 : 객체의 Getter Method 자동 생성하기

  • type alias는 interface보다 표현력이 더 풍부합니다.
    • 수많은 고급 type 기능(advanced type feature)들을 interface는 지원하지 않으며, 이러한 고급 기능들은 TypeScript가 발전함에 따라 계속해서 추가되고 있습니다.
  • 아래는 interface로 구현할 수 없는 고급 type 기능 구현 예제입니다.
    • 모든 object type 객체에 대해서, getter method를 자동으로 생성해주는 type alias입니다.
    • mapped type, template literal types, keyof 연산자(operator)를 사용합니다.
type Client = {
    name: string;
    address: string;
}

type Getters<T> = {
    [K in keyof T as `get${Capitalize<string & K>}`]:  () => T[K];
};

type clientType = Getters<Client>;
// type clientType = {
//     getName: () => string;
//     getAddress: () => string;
// }

Reference


목차