API 요청을 보낼 때는 일부 필드만 전송하고, 업데이트할 때는 수정한 필드만 보내는 경우가 많습니다. 기존 타입을 그대로 쓰면 맞지 않고, 새 타입을 따로 만들면 중복이 생깁니다. TypeScript는 이 문제를 해결하기 위한 유틸리티 타입을 내장하고 있습니다.
모든 프로퍼티를 선택적으로 만듭니다.
interface User {
id: number;
name: string;
email: string;
age: number;
}
type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; age?: number }
function updateUser(id: number, updates: Partial<User>) {
// 일부 필드만 업데이트 가능
}
updateUser(1, { name: "영희" }); // 정상
updateUser(1, { name: "영희", age: 25 }); // 정상
모든 선택적 프로퍼티를 필수로 만듭니다. Partial의 반대입니다.
interface Config {
host?: string;
port?: number;
debug?: boolean;
}
type RequiredConfig = Required<Config>;
// { host: string; port: number; debug: boolean }
function startServer(config: Required<Config>) {
// host, port, debug 모두 반드시 있어야 함
}
모든 프로퍼티를 읽기 전용으로 만듭니다.
interface User {
id: number;
name: string;
}
const user: Readonly<User> = { id: 1, name: "철수" };
user.name = "영희"; // 오류: 읽기 전용 프로퍼티에 할당할 수 없습니다
불변 객체를 표현하거나, 함수에서 매개변수를 수정하지 않겠다는 의도를 드러낼 때 사용합니다.
타입 T에서 특정 키 K만 추출합니다.
interface User {
id: number;
name: string;
email: string;
password: string;
createdAt: Date;
}
type UserProfile = Pick<User, "id" | "name" | "email">;
// { id: number; name: string; email: string }
// 비밀번호 없이 프로필만 반환
function getProfile(user: User): UserProfile {
return { id: user.id, name: user.name, email: user.email };
}
타입 T에서 특정 키 K를 제외합니다. Pick의 반대입니다.
type UserWithoutPassword = Omit<User, "password">;
// { id: number; name: string; email: string; createdAt: Date }
제외할 것이 적을 때는 Omit, 남길 것이 적을 때는 Pick이 더 편리합니다.
키 타입 K와 값 타입 V로 이루어진 객체 타입을 만듭니다.
type Role = "admin" | "editor" | "viewer";
type Permission = { read: boolean; write: boolean; delete: boolean };
const permissions: Record<Role, Permission> = {
admin: { read: true, write: true, delete: true },
editor: { read: true, write: true, delete: false },
viewer: { read: true, write: false, delete: false },
};
모든 키에 같은 구조의 값이 대응될 때 유용합니다.
유니온 타입 T에서 U에 해당하는 타입을 제거합니다.
type Animal = "dog" | "cat" | "fish" | "bird";
type Pet = Exclude<Animal, "fish">; // "dog" | "cat" | "bird"
유니온 타입 T에서 U에 해당하는 타입만 추출합니다. Exclude의 반대입니다.
type StringOrNumber = string | number | boolean;
type OnlyStringOrNumber = Extract<StringOrNumber, string | number>;
// string | number
null과 undefined를 제거합니다.
type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>; // string
함수 타입의 반환 타입을 추출합니다.
function getUser() {
return { id: 1, name: "철수" };
}
type UserResult = ReturnType<typeof getUser>;
// { id: number; name: string }
함수의 반환 타입을 직접 정의하지 않아도, 함수 구현을 바꾸면 ReturnType도 자동으로 갱신됩니다.
함수 타입의 매개변수 타입을 튜플로 추출합니다.
function createUser(name: string, age: number, email: string) {
return { name, age, email };
}
type CreateUserParams = Parameters<typeof createUser>;
// [name: string, age: number, email: string]
유틸리티 타입은 기존 타입을 재활용하는 핵심 도구입니다. 타입을 매번 새로 정의하는 대신 유틸리티 타입으로 변형하면, 원본 타입이 바뀌어도 파생 타입들이 자동으로 따라갑니다.