타입 별칭은 타입에 이름을 붙입니다. type Name = ...이라고 쓰면 그 뒤로 타입이 필요한 곳 어디서든 Name을 쓸 수 있습니다. 인터페이스와 달리 별칭은 객체 모양뿐 아니라 어떤 타입에든 이름을 붙일 수 있습니다.
별칭은 컴파일 시점에만 존재합니다. 출력된 JavaScript에는 이 type 줄이 하나도 없습니다.
문법
type Name = SomeType;
type Name<T> = SomeTypeUsing<T>; // generic
export type Name = SomeType; // exported from a module
이름은 관례상 PascalCase입니다. 오른쪽은 아무 타입 표현식이나 될 수 있고, 별칭은 다른 별칭을, 심지어 자기 자신도 쓸 수 있습니다(아래 재귀 타입 참고). 타입은 const나 let처럼 순서대로 실행되는 것이 아니라 컴파일 시점에 검사되므로, 별칭은 선언 줄보다 위를 포함해 선언된 스코프 전체에서 쓸 수 있습니다.
객체 타입
객체 모양이라면 별칭과 인터페이스의 작성법은 거의 같습니다. 별칭은 =를 쓰고 보통 세미콜론으로 끝냅니다.
별칭은 extends를 쓸 수 없고, & 교차 타입이 그 역할을 합니다. 초과 속성 검사, 선택적 속성, readonly 속성은 인터페이스와 똑같이 동작합니다. 객체 모양에 둘 중 무엇을 고를지는 interface와 type 비교 페이지에서 다룹니다.
유니언, 튜플, 함수
별칭만 이름을 붙일 수 있는 경우들이며, type이 존재하는 주된 이유입니다. 유니언 별칭은 선택지를 나열하고, 튜플 별칭은 배열의 길이와 요소 타입을 고정하며, 함수 별칭은 시그니처를 기술합니다.
scale의 매개변수에는 표기가 필요 없습니다. Transform 별칭이 타입을 제공합니다. 튜플 문법은 튜플에서, 유니언 좁히기는 유니언 타입 페이지에서 다룹니다.
제네릭 타입 별칭
타입 매개변수를 쓰면 별칭 하나로 여러 타입을 다룰 수 있습니다. 함수 매개변수처럼 기본값을 가질 수도 있습니다.
Result<number>는 기본값 E = string을 씁니다. type Nullable<T> = T | null이나 type Dict<T> = Record<string, T> 같은 작은 제네릭 별칭은 실제 코드에서 흔합니다. 내장 유틸리티 타입(Partial<T>, Pick<T, K>, ReturnType<F>)도 표준 라이브러리에 선언된 제네릭 별칭입니다.
별칭은 새 타입이 아니라 이름이다
별칭은 별개의 타입을 만들지 않습니다. 오른쪽 타입의 두 번째 이름이며, 컴파일러는 둘을 같은 것으로 취급합니다. string의 두 별칭은 완전히 바꿔 쓸 수 있습니다.
이 코드는 오류 없이 cancelling u_42를 출력하며, 이것이 별칭으로는 막을 수 없는 버그입니다. 별칭은 여전히 읽는 사람에게 도움이 되지만(OrderId 타입의 매개변수는 string보다 많은 것을 말합니다), 두 id를 뒤섞는 것이 컴파일 오류여야 한다면 string & { readonly __brand: "OrderId" } 같은 브랜드 타입을 쓰세요.
재귀 타입 별칭
별칭은 자기 자신을 참조할 수 있으며, 트리, 중첩 리스트, JSON을 이렇게 기술합니다.
Json 별칭은 JSON으로 표현할 수 없는 값을 거부합니다. { when: new Date() }나 { f: undefined }를 Json에 대입하면 컴파일 오류(TS2322)입니다.
값에서 타입 얻기: typeof
값이 이미 있다면 타입을 직접 쓰는 대신 그 값의 타입에 이름을 붙일 수 있습니다. typeof 타입 연산자는 변수의 타입을 읽고, 다른 연산자와 조합할 수 있습니다.
const defaults = { retries: 3, verbose: false, level: "info" };
type Options = typeof defaults;
// { retries: number; verbose: boolean; level: string }
type OptionKey = keyof typeof defaults;
// "retries" | "verbose" | "level"
function start(port: number) {
return { port, startedAt: new Date() };
}
type Server = ReturnType<typeof start>;
// { port: number; startedAt: Date }
값이 유일한 진실의 원천으로 남습니다. defaults에 속성을 추가하면 Options도 따라갑니다. 더 자세한 내용은 typeof에 있습니다.
별칭 내보내기와 가져오기
별칭은 값처럼 export하고 import합니다. import type은 타입만 가져온다는 것을 명시하므로, 그 import는 JavaScript 출력에서 항상 제거됩니다.
// shapes.ts
export type Point = { x: number; y: number };
export type Shape = { kind: "circle"; center: Point; radius: number };
// main.ts
import type { Point, Shape } from "./shapes.js";
const p: Point = { x: 1, y: 2 };
자주 묻는 질문
TypeScript에서 타입 별칭이란 무엇인가요?
타입 별칭은 type 키워드로 선언하는 타입의 이름입니다: type Point = { x: number; y: number }. 그 뒤로 타입이 필요한 곳 어디서든 Point를 쓸 수 있습니다. 객체 모양, 유니언, 튜플, 함수 시그니처, 원시 타입, 제네릭 타입 등 어떤 타입에든 이름을 붙일 수 있습니다.
타입 별칭은 새 타입을 만드나요?
아니요. 별칭은 기존 타입의 또 다른 이름일 뿐입니다. type UserId = string과 type OrderId = string이 있으면 둘 다 그냥 string이므로 OrderId가 필요한 곳에 UserId를 넘길 수 있습니다. 서로 바꿔 쓸 수 없는 타입을 만들려면 브랜드 타입을 쓰세요.
타입 별칭이 자기 자신을 참조할 수 있나요?
네, 자기 참조가 객체 타입, 배열, 튜플 안에 중첩되어 있다면 가능합니다. type TreeNode = { value: number; children: TreeNode[] }와 Json[]을 포함하는 Json 별칭 모두 동작합니다. type Loop = Loop | string 같은 맨 참조는 오류 TS2456, Type alias 'Loop' circularly references itself입니다.
타입 별칭을 제네릭으로 만들 수 있나요?
네. 이름 뒤에 타입 매개변수를 둡니다: type Box<T> = { value: T }로 선언하고 Box<number>로 씁니다. 매개변수에는 기본값(type Result<T, E = string> = ...)과 제약(type Keys<T extends object> = keyof T)을 줄 수 있습니다.
기존 객체에서 타입을 얻으려면 어떻게 하나요?
typeof 타입 연산자를 쓰세요. const defaults = { retries: 3, verbose: false }; type Options = typeof defaults;는 { retries: number; verbose: boolean }을 줍니다. 값이 먼저 있을 때 진실의 원천을 하나로 유지할 수 있습니다.