interface
객체(클래스, 구조체 등) 형태 정의
- 주로 객체 구조 정의
- extends로 확장
- 선언 병합 가능! (같은 이름 interface 여러 번 선언 시 자동 병합)
interface Person {
name: string;
}
interface Person {
age: number;
}
// 병합된 최종 Person 타입
const p: Person = {
name: "Alice",
age: 25
};
type
더 넓은 범위의 타입 별칭(Alias) 정의
- 객체 구조 + 기본 타입 + 유니온 + 튜플 + 제네릭 등 가능
- &(Intersection)으로 확장
- 선언 병합 불가능
1. 객체 형태 정의
interface User {
name: string;
age: number;
}
type UserType = {
name: string;
age: number;
};
두 방법 모두 동일하게 작동.
2. 확장 방법
// Interface 확장
interface User {
name: string;
}
interface Admin extends User {
role: string;
}
// Type 확장
type UserType = {
name: string;
};
type AdminType = UserType & { role: string };
3. 선언 병합
interface User {
name: string;
}
interface User {
age: number;
}
// 병합 결과: { name: string; age: number }
type UserType = { name: string };
// ❌ 아래는 에러 (type은 병합 불가)
// type UserType = { age: number };
4. 유니온, 튜플 등
// ✅ type 가능
type Status = "loading" | "success" | "error";
type Point = [number, number];
// ❌ interface 불가능 (유니온, 튜플 직접 표현 안 됨)
interface
- 객체, 클래스의 구조 정의에 최적
- 확장과 선언 병합 기능 덕에 라이브러리 타입 보강에 좋음
- 주로 "이 타입은 이렇게 생겼다"고 말할 때
type
- 유니온, 튜플, 기본 타입 별칭까지 가능 → 더 범용적
- 선언 병합은 안되지만 표현력이 더 강함
- 주로 "이 타입은 이런 범위를 가진다"라고 할 때
아직도 좀 헷갈리고 언제 뭘 써야하는지는 계속 헷갈릴 거 같다..;;
팀 컨벤션에 따라 둘 중 하나로 통일하기도 한다고 한다.
API 응답 타입 구조를 만들 때는 inferface랑 type, 제네릭을 섞어서 쓴다고 한다.
제네릭이 뭐더라...ㅎㅎ
제네릭
타입을 나중에 결정하는 템플릿!
type ApiResponse = {
data: string; // 무조건 string
isLoading: boolean;
};
제네릭을 사용하지 않았을 경우는 타입을 정의하면 속성 타입이 고정됨!
type ApiResponse<T> = {
data: T;
isLoading: boolean;
};
제네릭을 사용하면 타입을 변수처럼 받아서 data의 타입을 고정시키지 않고 사용 가능
// 문자열을 응답으로 하는 API
const storyResponse: ApiResponse<string> = {
data: "정릉에서 찍은 사진이에요",
isLoading: false,
};
// 배열을 응답으로 하는 API
const storyListResponse: ApiResponse<string[]> = {
data: ["사진1", "사진2"],
isLoading: false,
};
// 객체를 응답으로 하는 API
type Story = { id: string; content: string };
const storyObjResponse: ApiResponse<Story> = {
data: { id: "123", content: "오늘은 맑음" },
isLoading: true,
};
이렇게 사용이 가능하다.
즉,
API 응답 “껍데기” (즉, data, isLoading, error 같은 공통 구조)는
type + 제네릭으로 만들어서 재사용성과 유연성을 극대화
내부 데이터 구조 (예: Story, EmotionTag 등 실제 비즈니스 도메인 타입)는
interface로 정의해서 확장이나 선언 병합 같은 이점 활용
// 껍데기
type ApiResponse<T> = {
data: T;
isLoading: boolean;
error?: string;
}
// 도메인 데이터
interface Story {
id: string;
content: string;
emotions: string[];
createdAt: string;
}
// ApiResponse에 Story 끼워넣기
type StoryResponse = ApiResponse<Story>;
이렇게 예제로 보니 좀 이해가 되는 거 같다.
이번 프로젝트 때 써봐야겠다!

'개발 > TypeScript' 카테고리의 다른 글
[TypeScript] TypeScript의 모듈화 (0) | 2024.12.11 |
---|---|
[TypeScript] TypeScript의 비동기 함수 (0) | 2024.12.11 |
[TypeScript] TypeScript의 상수 단언 (0) | 2024.12.11 |
[TypeScript] TypeScript의 유틸리티 타입 (0) | 2024.12.10 |
[TypeScript] TypeScript의 고급 타입 (1) | 2024.12.10 |