타입 별칭
복잡한 유니온·인터섹션·객체 타입에 재사용 가능한 이름을 붙이고 확장 방식에 따라 type과 interface를 선택합니다.
우리는 객체의 모양을 정의할 때 interface를 사용하는 방법을 배웠습니다.
interface는 주로 객체의 타입을 정의하고, 확장하거나 구현할 때 강력한 도구입니다.
하지만 타입스크립트에는 이 외에도 복잡한 타입을 간결하게 재사용할 수 있도록 돕는 또 다른 강력한 기능이 있는데, 바로 타입 별칭(Type Aliases)입니다.
타입 별칭은 기존에 존재하는 타입에 새로운 이름(별칭)을 부여하는 방법입니다.
이를 통해 복잡한 유니온 타입, 인터섹션 타입, 혹은 객체 리터럴 타입을 더 읽기 쉽고 관리하기 쉬운 이름으로 만들 수 있습니다.
마치 긴 주소를 짧은 별명으로 부르는 것과 같습니다.
TYPE ALIAS · DATA FLOW
타입 별칭은 구조에 이름을 붙인다
임의의 타입 식은 별칭으로 재사용되지만 구조적 할당 가능성은 그대로이며 emit 뒤에는 별칭 자체가 남지 않습니다.
- 타입 식
유니온·튜플·함수·객체 등 임의의 타입을 시작점으로 둡니다.
- 재사용 이름
type은 읽을 수 있는 이름을 붙이지만 새 값은 만들지 않습니다.
- 구조적 할당
이름보다 실제 멤버 구조로 호환성을 검사합니다.
- 타입 소거
emit 뒤에는 별칭 없이 JavaScript 값만 남습니다.
별칭만으로 의미가 다른 ID를 nominal하게 분리할 수 없으며 런타임 검증이나 brand는 별도의 설계입니다.
타입 별칭 정의하기
타입 별칭은 type 키워드를 사용하여 정의합니다.
// string 타입에 'Name'이라는 별칭을 부여합니다.
type Name = string;
let myName: Name = "김타입";
// number 타입에 'Age'라는 별칭을 부여합니다.
type Age = number;
let myAge: Age = 30;
// 유니온 타입에 별칭을 부여합니다.
type Id = string | number;
let userId: Id = "user_007";
let adminId: Id = 1004;
// 인터섹션 타입에 별칭을 부여합니다.
type Point = { x: number; y: number };
type ZCoordinate = { z: number };
type ThreeDPoint = Point & ZCoordinate;
let point3d: ThreeDPoint = { x: 10, y: 20, z: 30 };
console.log(myName); // 김타입
console.log(userId); // user_007
console.log(point3d.z); // 30위 예시에서 볼 수 있듯이, type 키워드 뒤에 별칭으로 사용할 이름을 쓰고, 등호(=) 뒤에 별칭을 부여할 타입을 정의합니다.
이렇게 정의된 별칭은 원래의 타입을 사용하는 것처럼 어디든 사용할 수 있습니다.
객체 타입 정의에 타입 별칭 사용하기
타입 별칭은 특히 객체 타입을 정의할 때 매우 유용합니다.
interface와 유사하게 객체의 모양을 정의할 수 있습니다.
// 'User'라는 타입 별칭으로 객체 타입을 정의합니다.
type User = {
id: string;
name: string;
email?: string; // 선택적 속성
readonly registrationDate: Date; // 읽기 전용 속성
};
let currentUser: User = {
id: "u_abc",
name: "이코딩",
registrationDate: new Date(),
};
let newUser: User = {
id: "u_xyz",
name: "박개발",
email: "park@example.com",
registrationDate: new Date("2024-01-01"),
};
console.log(currentUser.name); // 이코딩
// newUser.registrationDate = new Date(); // Error: registrationDate는 읽기 전용입니다.이전 2장 3절에서 interface로 정의했던 Person과 거의 동일하게 User 타입을 정의했음을 알 수 있습니다.
인터페이스와 타입 별칭의 차이점
타입 별칭과 인터페이스는 객체의 타입을 정의하는 데 모두 사용될 수 있어 비슷하게 느껴질 수 있습니다.
하지만 몇 가지 중요한 차이점이 있습니다.
- 인터페이스:
extends키워드를 사용하여 다른 인터페이스를 확장할 수 있고, 클래스가implements키워드를 사용하여 인터페이스를 구현할 수 있습니다. 이는 객체 지향적인 상속과 계약 관계를 명확히 표현할 때 유리합니다. - 타입 별칭: 별칭 선언 자체는
type 이름 = 타입형태이고, 인터섹션(&)으로 객체 요구를 결합할 수 있습니다. 정적으로 알려진 멤버를 가진 객체형 별칭은 인터페이스의extends나 클래스의implements대상도 될 수 있습니다. 유니온 별칭은 이 대상이 될 수 없습니다.
// 인터페이스 확장 (extends)
interface BaseShape {
color: string;
}
interface Circle extends BaseShape {
radius: number;
}
// 타입 별칭을 이용한 '확장' (인터섹션 &)
type BaseShapeAlias = {
color: string;
};
type CircleAlias = BaseShapeAlias & {
radius: number;
};- 인터페이스: 동일한 이름으로 여러 번 선언해도 자동으로 병합(Merge)됩니다. 이는 라이브러리에서 기존 타입에 새로운 속성을 추가하는 등의 상황에서 유용합니다.
- 타입 별칭: 동일한 이름으로 여러 번 선언할 수 없습니다. 즉, 재선언 시 오류가 발생합니다.
// 인터페이스 병합 예시
interface Car {
brand: string;
}
interface Car { // 동일한 이름으로 다시 선언해도 오류 없음
model: string;
}
let myCar: Car = { brand: "BMW", model: "X5" }; // brand와 model 모두 가짐
// 타입 별칭 재선언 시 오류
// type Product = { name: string };
// type Product = { price: number }; // Error: Duplicate identifier 'Product'.- 타입 별칭: 원시 타입, 유니온, 튜플 등 모든 종류의 타입에 별칭을 부여할 수 있습니다.
- 인터페이스: 주로 객체의 모양을 정의하는 데 사용되며, 원시 타입이나 유니온, 튜플을 직접적으로 정의할 수는 없습니다. (물론 인터페이스 내부 속성으로는 가능합니다.)
type StringOrNumber = string | number; // 타입 별칭은 유니온 타입에 사용 가능
type PointTuple = [number, number]; // 타입 별칭은 튜플 타입에 사용 가능
// interface MyPrimitive extends string {} // Error: 인터페이스는 원시 타입을 확장할 수 없습니다.아래 다이어그램은 interface와 type 별칭을 선택할 때 확인할 기준을 프로젝트 적용 관점에서 정리한 것입니다.
CAPABILITY BOUNDARY · FLOWCHART
type과 interface를 표현 능력으로 고르기
선호도 경쟁 대신 표현할 타입 식, 선언 병합 정책, extends와 implements의 실제 compiler 제약을 질문합니다.
- 임의 타입 식
유니온·튜플·조건부 타입에는 type을 사용합니다.
- 열린 선언 병합
소비자가 같은 이름을 확장해야 하면 interface 정책을 명시합니다.
- 객체 확장
정적으로 알려진 object members인지 compiler 제약을 확인합니다.
- 클래스 구현
object-shaped alias와 interface는 가능하지만 union은 구현할 수 없습니다.
교차 타입 충돌은 never가 될 수 있고 interface extends는 충돌을 진단하므로 두 확장 방식을 같은 결과로 가정하지 않습니다.
타입 별칭과 인터페이스는 기능이 겹치는 부분이 많기 때문에 팀 규칙 없이 섞어 쓰면 읽는 사람이 의도를 추측해야 합니다.
언제 무엇을 사용해야 할까?
일반적인 가이드라인은 다음과 같습니다.
- 객체의 모양(Shape)을 정의하고, 향후 다른 인터페이스가 이를 확장하거나 클래스가 구현해야 할 가능성이 있다면
interface를 사용하는 것이 좋습니다. 특히 라이브러리나 프레임워크처럼 확장성이 중요한 설계에서는interface가 더 강력한 도구입니다. - 원시 타입, 유니온 타입, 튜플 타입 등 객체 이외의 타입을 포함하여 어떤 타입이든 간결하게 별칭을 부여하고 싶을 때는
type별칭을 사용합니다.interface로는 표현하기 어려운 복잡한 조합의 타입을 정의할 때 유용합니다.
최근 타입스크립트 버전에서는 interface와 type 별칭의 기능적 차이가 많이 줄어들었지만, 위에서 언급한 주요 차이점들은 여전히 유효합니다.
프로젝트의 성격과 팀의 컨벤션에 따라 선택하여 사용할 수 있습니다.
이로써 타입스크립트의 기본 타입들에 대한 학습을 마쳤습니다.
숫자, 문자열, 불리언과 같은 기본 데이터부터 시작하여, 복잡한 객체와 그 형태를 정의하는 인터페이스, 그리고 유연한 타입 조합을 위한 유니온/인터섹션, 마지막으로 타입에 새 이름을 부여하는 타입 별칭까지, 타입스크립트의 견고한 타입 시스템을 위한 핵심 개념들을 살펴보았습니다.