Interface가 객체의 형태를 정의하는 데 특화되어 있다면, Type Alias는 더 넓은 범위의 타입에 이름을 붙이는 기능입니다. 유니온 타입, 튜플, 함수 타입 등 Interface로 표현하기 어색한 것들도 Type Alias로는 간단히 정의할 수 있습니다.
type 키워드로 새로운 타입 이름을 만듭니다.
type UserId = number;
type UserName = string;
let id: UserId = 1;
let name: UserName = "철수";
단순한 이름 변경처럼 보이지만, 의미 있는 이름을 붙여 코드의 의도를 명확히 합니다. number 대신 UserId라고 쓰면 이 값이 사용자 ID임을 바로 알 수 있습니다.
Interface와 마찬가지로 객체의 형태를 정의할 수 있습니다.
type User = {
name: string;
age: number;
email?: string;
};
const user: User = { name: "철수", age: 30 };
여러 타입 중 하나를 허용하는 유니온 타입에 이름을 붙일 수 있습니다. Interface로는 표현할 수 없는 형태입니다.
type Status = "pending" | "active" | "inactive";
type ID = number | string;
type StringOrNumber = string | number;
function processId(id: ID) {
if (typeof id === "string") {
return id.toUpperCase();
}
return id.toString();
}
유니온 타입(Union Type): 두 개 이상의 타입 중 하나가 될 수 있는 타입. | 연산자로 표현합니다.
함수의 매개변수와 반환 타입에 이름을 붙입니다.
type Formatter = (value: string) => string;
type AsyncCallback = (error: Error | null, result?: string) => void;
const toUpperCase: Formatter = (value) => value.toUpperCase();
const trim: Formatter = (value) => value.trim();
type Point = [number, number];
type RGB = [number, number, number];
const origin: Point = [0, 0];
const red: RGB = [255, 0, 0];
두 가지 모두 객체 타입을 정의할 수 있어 혼용되는 경우가 많습니다. 차이점을 알고 상황에 맞게 선택합니다.
| Interface | Type Alias | |
|---|---|---|
| 객체 타입 정의 | 가능 | 가능 |
| 유니온 타입 | 불가능 | 가능 |
| 튜플 | 불가능 | 가능 |
| 선언 병합 | 가능 | 불가능 |
| extends | 가능 | & 교차 타입으로 가능 |
| 재귀 타입 | 가능 | 가능 |
선언 병합이 필요할 때, 또는 클래스가 implements해야 할 때 Interface를 사용합니다.
interface Repository<T> {
find(id: number): T;
save(entity: T): void;
}
class UserRepository implements Repository<User> {
find(id: number): User { /* ... */ }
save(entity: User): void { /* ... */ }
}
유니온 타입, 튜플, 프리미티브 타입에 이름을 붙이는 경우에는 Type Alias를 사용합니다.
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type Coordinates = [number, number];
type NullableString = string | null;
Type Alias는 extends 대신 & 교차 타입으로 합칩니다.
type Animal = {
name: string;
age: number;
};
type Dog = Animal & {
breed: string;
};
const dog: Dog = {
name: "뭉치",
age: 3,
breed: "말티즈",
};
교차 타입(Intersection Type): 두 타입의 모든 프로퍼티를 합친 타입. & 연산자로 표현합니다. 두 타입을 모두 만족해야 합니다.
자기 자신을 참조하는 타입도 만들 수 있습니다. 트리 구조나 중첩된 데이터를 표현할 때 유용합니다.
type TreeNode = {
value: number;
children?: TreeNode[];
};
const tree: TreeNode = {
value: 1,
children: [
{ value: 2 },
{ value: 3, children: [{ value: 4 }] },
],
};
명확한 선택 기준이 없다면 객체 타입에는 Interface, 그 외 나머지(유니온, 튜플, 함수 타입 등)에는 Type Alias를 쓰는 방식이 팀 내 일관성을 유지하는 데 도움이 됩니다.