TypeScript는 정적 타입을 지원하는 강력한 언어로, 사용자 정의 타입을 정의할 때 주로 type과 interface를 사용합니다. 이들은 비슷한 역할을 하지만 약간의 차이가 있습니다. 이 블로그 포스팅에서는 두 가지의 용도와 차이점을 자세히 살펴보겠습니다.
type: 유니온 타입과 복잡한 타입 정의에 유용
type은 다음과 같은 상황에 주로 사용됩니다:
- 유니온 타입, 인터섹션 타입 등 복잡한 타입 정의: type을 사용하면 유니온 타입(|)과 인터섹션 타입(&)과 같은 타입 연산자를 활용하여 복잡한 타입을 정의할 수 있습니다. 이것은 코드의 가독성과 재사용성을 높이는 데 도움이 됩니다.
type User = {
id: number;
username: string;
};
type Admin = {
id: number;
role: string;
};
type UserOrAdmin = User | Admin;
- 단순한 타입 별칭: 기본 데이터 타입을 단순화하거나 직관적으로 명명하는 데 사용됩니다.
type Point = {
x: number;
y: number;
};
- 조건부 타입: type을 사용하여 조건부 타입을 정의할 수 있으며, 이를 통해 타입 검사와 유연한 타입 정의를 할 수 있습니다.
type ResponseType<T> = T extends 'json' ? { data: any } : string;
interface: 객체의 구조를 정의하고 클래스와 관계 설정
interface는 다음과 같은 상황에 주로 사용됩니다:
- 객체의 구조(shape) 정의: interface를 사용하면 객체의 구조를 정의하고 해당 인터페이스를 따르는 객체를 생성할 수 있습니다. 이것은 클래스나 함수 매개변수에서 사용될 때 매우 유용합니다.
interface User {
id: number;
username: string;
}
const user: User = {
id: 1,
username: 'exampleUser',
};
- 클래스와 인터페이스의 관계: interface를 사용하여 클래스와 관련된 메서드와 속성을 정의할 수 있으며, 클래스가 해당 인터페이스를 구현(implements)하도록 할 수 있습니다.
interface Animal {
makeSound(): void;
}
class Dog implements Animal {
makeSound() {
console.log('Woof! Woof!');
}
}
- 객체의 확장: interface는 확장이 가능하며, 다른 인터페이스를 확장하여 새로운 인터페이스를 정의할 수 있습니다.
interface Person {
name: string;
age: number;
}
interface Address {
city: string;
postalCode: string;
}
interface Contact extends Person, Address {
email: string;
}
- 덕 타이핑(Duck Typing): TypeScript에서 객체의 타입은 해당 객체가 필요로 하는 속성과 메서드를 정의하는 인터페이스와 관련이 있습니다. 이를 통해 덕 타이핑을 지원하며 객체의 형태에 따라 타입을 검사합니다.
interface Quackable {
quack(): void;
}
function makeItQuack(duck: Quackable) {
duck.quack();
}
중요한 차이점: type은 유니온 타입과 인터섹션 타입을 생성하고, interface는 객체의 구조를 정의하고 클래스와의 관계를 설정합니다. 코드베이스에 따라 type과 interface를 혼용하여 사용하거나 두 가지 중 하나를 선택할 수 있습니다. 일반적으로는 interface를 객체 구조를 정의하고 클래스와의 관계를 설정하기 위해 사용하고, type은 복잡한 타입 연산 및 타입 별칭에 사용됩니다.