본문으로 건너뛰기

타입 별칭과 인터페이스

타입 별칭

우리는 객체 타입과 합집합 타입을 타입 주석에 직접 작성하여 사용해 왔습니다. 이 방법도 편리하지만, 동일한 타입을 두 번 이상 사용할 때는 하나의 이름으로 참조하는 것이 일반적입니다.

타입 별칭은 정확히 그 역할을 수행합니다. 즉, 타입 별칭은 타입의 이름입니다. 타입 별칭의 구문은 다음과 같습니다.

ts
type Point = {
x: number;
y: number;
};
 
// 이전 예시와 완전히 동일합니다.
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
 
printCoord({ x: 100, y: 100 });
ts
type Point = {
x: number;
y: number;
};
 
// 이전 예시와 완전히 동일합니다.
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
 
printCoord({ x: 100, y: 100 });

사실 타입 별칭을 사용하면 객체 타입뿐만 아니라 모든 타입의 이름을 지정할 수 있습니다. 예를 들어 타입 별칭은 합집합 타입의 이름을 지정할 수 있습니다.

ts
type ID = number | string;
ts
type ID = number | string;

별칭은 별칭일 뿐입니다. 타입 별칭을 사용하여 동일한 타입의 서로 다른(고유한) 버전을 만들 수는 없습니다. 별칭을 사용한다는 것은 타입의 별칭을 작성하는 것입니다. 다음 코드는 잘못된 것처럼 보일 수 있지만, 타입스크립트에 따르면 두 타입은 동일한 타입의 별칭이기 때문에 문제가 없습니다.

ts
type UserInputSanitizedString = string;
 
function sanitizeInput(str: string): UserInputSanitizedString {
return sanitize(str);
}
 
// 살균된 입력을 생성합니다.
let userInput = sanitizeInput(getInput());
 
// 여전히 문자열을 사용하여 재할당할 수 있습니다.
userInput = "new input";
ts
type UserInputSanitizedString = string;
 
function sanitizeInput(str: string): UserInputSanitizedString {
return sanitize(str);
}
 
// 살균된 입력을 생성합니다.
let userInput = sanitizeInput(getInput());
 
// 여전히 문자열을 사용하여 재할당할 수 있습니다.
userInput = "new input";

인터페이스

인터페이스 선언은 객체 타입의 이름을 지정하는 또 다른 방법입니다.

ts
interface Point {
x: number;
y: number;
}
 
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
 
printCoord({ x: 100, y: 100 });
ts
interface Point {
x: number;
y: number;
}
 
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
 
printCoord({ x: 100, y: 100 });

앞에서 타입 별칭을 사용했을 때와 마찬가지로, 이 예시는 익명 객체 타입을 사용한 것처럼 작동합니다. 타입스크립트는 printCoord에 전달한 값의 구조에만 관심이 있습니다. 예상되는 프로퍼티의 존재 여부에만 관심이 있습니다.

타입의 구조와 기능에만 관심을 가지기 때문에, 우리는 타입스크립트를 구조적으로 타입이 지정된 타입 시스템이라고 부릅니다.

타입 별칭과 인터페이스의 차이점

타입 별칭과 인터페이스는 매우 유사하며, 대부분의 경우 자유롭게 선택할 수 있습니다. interface의 거의 모든 기능은 type에서도 제공됩니다. 주요 차이점은 인터페이스는 항상 확장 가능한 반면, 타입은 새 프로퍼티를 추가하기 위해 다시 열 수 없다는 점입니다.

인터페이스

인터페이스 확장하기

ts
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;
ts
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;

기존 인터페이스에 새 필드 추가하기

ts
interface Window {
title: string;
}
interface Window {
ts: TypeScriptAPI;
}
const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});
ts
interface Window {
title: string;
}
interface Window {
ts: TypeScriptAPI;
}
const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});

타입

교집합을 통해 타입 확장하기

ts
type Animal = {
name: string;
}
type Bear = Animal & {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;
ts
type Animal = {
name: string;
}
type Bear = Animal & {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;

생성된 후에는 타입을 변경할 수 없습니다.

ts
type Window = {
title: string;
}
type Window = {
ts: TypeScriptAPI;
}
// 오류: Duplicate identifier 'Window'.
ts
type Window = {
title: string;
}
type Window = {
ts: TypeScriptAPI;
}
// 오류: Duplicate identifier 'Window'.

이후의 장에서 이 개념에 대해 자세히 배우므로, 모든 내용을 바로 이해하지 못하더라도 걱정하지 마세요.

대부분의 경우 개인 취향에 따라 선택할 수 있으며, 다른 종류의 선언이 필요한 경우 타입스크립트에서 알려줍니다. 경험적 접근(휴리스틱)을 원한다면, type의 기능이 필요하기 전까지는 interface를 사용하세요.