SHIN STORYSHIN STORY
홈포스트C#TypeScriptNext.jsNode.js시리즈
</>SHIN STORY

sdf

탐색

  • 홈
  • 모든 포스트
  • 시리즈
  • 검색

카테고리

  • C#
  • TypeScript
  • Next.js
  • Node.js
  • 알고리즘
  • 개발 도구

© 2025 Shin Blog. All rights reserved.

GitHubRSS
목록으로
TypeScript#TypeScript

TypeScript 팁 #2 — 유틸리티 타입 완전 정복

SHIN

2025년 4월 17일2분 읽기0
📚

TypeScript 실전 팁 10선

10편
  1. 5TypeScript 팁 #5 — 타입 가드로 런타임 타입 좁히기
  2. 6TypeScript 팁 #6 — 매핑 타입으로 타입 변환하기
  3. 10TypeScript 팁 #1 — strict 모드를 반드시 켜야 하는 이유
  4. TypeScript 팁 #2 — 유틸리티 타입 완전 정복현재
  5. 10TypeScript 팁 #3 — 판별 유니온으로 타입 안전한 상태 관리
  6. 10TypeScript 팁 #4 — 제네릭 제약 조건과 infer 활용
  7. 10TypeScript 팁 #7 — 템플릿 리터럴 타입으로 문자열 타입 조작
  8. 10TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기
  9. 10TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴
  10. 10TypeScript 팁 #10 — 타입 성능 최적화와 실무 패턴

TypeScript 팁 #2 — 유틸리티 타입 완전 정복

유틸리티 타입을 잘 활용하면 중복 타입 선언 없이 기존 타입에서 파생 타입을 만들 수 있습니다.

기본 인터페이스

CODE
interface User {
  id: number
  name: string
  email: string
  password: string
  createdAt: Date
  role: 'admin' | 'user'
}

Partial<T> — 모든 필드를 선택적으로

CODE
// 업데이트 시 일부 필드만 전달
function updateUser(id: number, data: Partial<User>) {
  // data.name, data.email 등 원하는 필드만 전달 가능
}

updateUser(1, { name: '홍길동' })          // ✅
updateUser(1, { name: '홍', email: 'a@b' }) // ✅

Required<T> — 모든 필드를 필수로

CODE
interface Config {
  host?: string
  port?: number
  timeout?: number
}

// 모든 설정값이 채워진 완성 상태
type ResolvedConfig = Required<Config>
// { host: string; port: number; timeout: number }

Pick<T, K> — 원하는 필드만 선택

CODE
// 공개 API 응답용 — 비밀번호 제외
type PublicUser = Pick<User, 'id' | 'name' | 'email'>

// 로그인 폼용
type LoginForm = Pick<User, 'email' | 'password'>

Omit<T, K> — 특정 필드 제거

CODE
// 생성 요청 — id와 createdAt은 서버에서 자동 생성
type CreateUserDto = Omit<User, 'id' | 'createdAt'>

// Pick보다 Omit이 더 편할 때: 제거할 필드가 선택할 필드보다 적을 때

Record<K, V> — 맵 타입 생성

CODE
// 역할별 권한 정의
type Permissions = Record<User['role'], string[]>

const permissions: Permissions = {
  admin: ['read', 'write', 'delete'],
  user:  ['read'],
}

// 키 타입을 유니온으로 제한
type StatusMap = Record<'pending' | 'active' | 'inactive', boolean>

ReturnType<T> — 함수 반환 타입 추출

CODE
async function fetchUser(id: number) {
  return { id, name: '홍길동', email: 'hong@example.com' }
}

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

// 라이브러리 함수의 반환 타입을 재사용할 때 특히 유용

Parameters<T> — 함수 파라미터 타입 추출

CODE
function createPost(title: string, content: string, tags: string[]) {}

type PostParams = Parameters<typeof createPost>
// [title: string, content: string, tags: string[]]

// 첫 번째 파라미터만 추출
type TitleParam = Parameters<typeof createPost>[0]  // string

Readonly<T> — 불변 객체

CODE
const config: Readonly<Config> = {
  host: 'localhost',
  port: 3000,
  timeout: 5000,
}

config.port = 8080  // ❌ 컴파일 오류: 읽기 전용 속성

유틸리티 타입 조합

CODE
// 업데이트 DTO: id 제외, 나머지는 선택적
type UpdateUserDto = Partial<Omit<User, 'id' | 'createdAt'>>

// API 응답: 비밀번호 제외, 모두 읽기 전용
type UserResponse = Readonly<Omit<User, 'password'>>

유틸리티 타입을 조합하면 단 한 줄로 복잡한 파생 타입을 표현할 수 있습니다.

공유
S

SHIN

.NET 개발자입니다

GitHub
TypeScript 팁 #1 — strict 모드를 반드시 켜야 하는 이유

이전 포스트

TypeScript 팁 #1 — strict 모드를 반드시 켜야 하는 이유

다음 포스트

TypeScript 팁 #3 — 판별 유니온으로 타입 안전한 상태 관리

TypeScript 팁 #3 — 판별 유니온으로 타입 안전한 상태 관리

같은 카테고리 포스트

TypeScript 팁 #10 — 타입 성능 최적화와 실무 패턴

TypeScript 팁 #10 — 타입 성능 최적화와 실무 패턴

2025년 5월 3일· 3분
TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴

TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴

2025년 5월 1일· 2분
TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기

TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기

2025년 4월 29일· 2분

댓글