개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

유틸리티 타입 — 기존 타입을 변환하는 내장 도구

2025년 11월 20일
TypeScriptUtility Types타입PartialPickOmit

API 요청을 보낼 때는 일부 필드만 전송하고, 업데이트할 때는 수정한 필드만 보내는 경우가 많습니다. 기존 타입을 그대로 쓰면 맞지 않고, 새 타입을 따로 만들면 중복이 생깁니다. TypeScript는 이 문제를 해결하기 위한 유틸리티 타입을 내장하고 있습니다.

Partial<T>

모든 프로퍼티를 선택적으로 만듭니다.

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 }); // 정상

Required<T>

모든 선택적 프로퍼티를 필수로 만듭니다. 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 모두 반드시 있어야 함
}

Readonly<T>

모든 프로퍼티를 읽기 전용으로 만듭니다.

interface User {
  id: number;
  name: string;
}

const user: Readonly<User> = { id: 1, name: "철수" };
user.name = "영희"; // 오류: 읽기 전용 프로퍼티에 할당할 수 없습니다

불변 객체를 표현하거나, 함수에서 매개변수를 수정하지 않겠다는 의도를 드러낼 때 사용합니다.

Pick<T, K>

타입 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 };
}

Omit<T, K>

타입 T에서 특정 키 K를 제외합니다. Pick의 반대입니다.

type UserWithoutPassword = Omit<User, "password">;
// { id: number; name: string; email: string; createdAt: Date }

제외할 것이 적을 때는 Omit, 남길 것이 적을 때는 Pick이 더 편리합니다.

Record<K, V>

키 타입 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 },
};

모든 키에 같은 구조의 값이 대응될 때 유용합니다.

Exclude<T, U>

유니온 타입 T에서 U에 해당하는 타입을 제거합니다.

type Animal = "dog" | "cat" | "fish" | "bird";
type Pet = Exclude<Animal, "fish">; // "dog" | "cat" | "bird"

Extract<T, U>

유니온 타입 T에서 U에 해당하는 타입만 추출합니다. Exclude의 반대입니다.

type StringOrNumber = string | number | boolean;
type OnlyStringOrNumber = Extract<StringOrNumber, string | number>;
// string | number

NonNullable<T>

null과 undefined를 제거합니다.

type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>; // string

ReturnType<T>

함수 타입의 반환 타입을 추출합니다.

function getUser() {
  return { id: 1, name: "철수" };
}

type UserResult = ReturnType<typeof getUser>;
// { id: number; name: string }

함수의 반환 타입을 직접 정의하지 않아도, 함수 구현을 바꾸면 ReturnType도 자동으로 갱신됩니다.

Parameters<T>

함수 타입의 매개변수 타입을 튜플로 추출합니다.

function createUser(name: string, age: number, email: string) {
  return { name, age, email };
}

type CreateUserParams = Parameters<typeof createUser>;
// [name: string, age: number, email: string]

유틸리티 타입은 기존 타입을 재활용하는 핵심 도구입니다. 타입을 매번 새로 정의하는 대신 유틸리티 타입으로 변형하면, 원본 타입이 바뀌어도 파생 타입들이 자동으로 따라갑니다.

← 이전 글제네릭 — 타입을 변수처럼 다루기
다음 글 →keyof와 typeof — 타입에서 타입을 만드는 연산자