[TypeScript] 섹션10. 유틸리티 타입

jaehoon ahn·2025년 2월 24일

TypeScript

목록 보기
14/14
post-thumbnail

유틸리티 타입 소개

유틸리티 타입

제네릭, 맵드 타입, 조건부 타입 등의 탕비 조작 기능을 이용해 실무에서 자주 사용되는 타입을 미리 만들어 놓은 것

예시1

interface Person {
  name: string;
  age: number;
}

const person: Readonly<Person> = {
  name: "제노",
  age: 28,
};
person.name = "";
// 모두 readonly로 바꿔줌

Partial 사용 예시

// 모든 프로퍼티를 선택적 프로퍼티로 바꾸는 유틸리티 타입
interface Person {
  name: string;
  age: number;
}

const person2: Partial<Person> = {
  name: "제노",
};

맵드 타입 기반

Partial<T>, Pick<T, K>;
Required<T>, Omit<T, K>;
Readonly<T>, Record<K, V>;

조건부 타입 기반

Exclude<T, U>, Extract<T, U>, ReturnType<T>;
// 이외에도 다양한 타입이 존재한다.

맵드 타입 기반의 유틸리티 타입 1 - Partial, Required, Readonly

Partial

부분적인, 일부분의

특정 객체 타입의 모든 프로퍼티를 선택적 프로퍼티로 바꿔주는 타입

예제

interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const draft: Post = {
  title: "제목 나중에 짓자",
  content: "초안...",
  //   tags가 없어서 오류 발생
};

⇒ tags가 없어서 오류 발생

const draft: Partial<Post> = {
  title: "제목 나중에 짓자",
  content: "초안...",
};

⇒ 선택적 프로퍼티로 타입을 정해줘서 오류 해결

Partial타입 구현하기

type Partial<T> = {
  [key in keyof T]?: T[key];
  // keyof: 특정 객체 타입으로부터 모든 키를 유니온 타입으로 추출하는 연산자
  // title | tags | content | thumbnailURL이 된다.
  // in: 왼쪽의 키가 오른쪽의 유니온 타입에 맵핑이 된다.
  // 즉, 한번은 title, 한번은 tags, 한번은 content, 한번은 thumbnailURL이 된다.
  // T[key]: 인덱스으 액세스 타입
  // 특정 객체나 배열로부터 특정 프로퍼티의 타입을 추출하는 타입
  // 즉, 타입변수 T에 들어온 객체타입으로부터 key에 해당하는 프로퍼티의 value 타입을 추출하는 것
};

Required

필수의, 필수적인

특정 객체 타입의 모든 프로퍼티를 필수 프로퍼티로 바꿔주는 타입

예제

const withThumbnailPost: Required<Post> = {
  title: "한입 타스 후기",
  tags: ["ts"],
  content: "",
  //   thumbnailURL이 없어서 오류 발생 => Required타입으로 오류 해결
};

Required 구현하기

type Required<T> = {
  [key in keyof T]-?: T[key];
};

Readonly

읽기 전용 수정 불가

특정 객체 타입에서 모든 프로퍼티를 읽기 전용 프로퍼티로 만들어주는 타입

const readonlyPost: Readonly<Post> = {
  title: "보호된 게시글 입니다.",
  tags: [],
  content: "",
};
readonlyPost.content = ""; // readonly라 오류 발생 => Readonly타입으로 오류 해결

Readonly 구현하기

type Readonly<T> = {
  readonly [key in keyof T]: T[key];
};

맵드 타입 기반의 유틸리티 타입 2 - Pick, Omit, Record

Pick<T, K>

뽑다, 고르다

객체 타입으로부터 특정 프로퍼티만 딱 골라내는 타입

예제

interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}
const legacyPost = {
  title: "옛날 글",
  content: "옛날 컨텐츠",
};
// tag가 없어서 Post 타입으로 정의할 수 없다.

Pick타입 사용법

const legacyPost: Pick<Post, "title" | "content"> = {
  title: "옛날 글",
  content: "옛날 컨텐츠",
};

Pick타입 구현하기

type Pick<T, K extends keyof T> = {
  // k extends 'title' | 'tags' | 'content' | 'thumbnailURL'
  // 'title' | 'content' extends 'title' | 'tags' | 'content' | 'thumbnailURL'
  [key in K]: T[key];
};

Omit<T, K>

생략하다, 빼다

Pick과 반대로 객체 타입으로부터 특정 프로퍼티를 제거하는 타입

const noTitlePost: Post = {
  content: "",
  tags: [],
  thumbnailURL: "",
//  title이 없어서 오류 발생
};
const noTitlePost: Omit<Post, "title"> = {
  content: "",
  tags: [],
  thumbnailURL: "",
};
// title을 제거해서 오류 제거

Omit 구현하기

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>
// T = Post, K = "title"
// Pick<Post, Exclude<keyof Post, 'title'>>
// Pick<Post, Exclude<'title' | 'content' | 'tags' | 'thumbnailURL', 'title'>>
// Pick<Post, 'content' | 'tags' | 'thumbnailURL' >

Record<K, V>

type ThumbnailLegacy = {
  large: {
    url: string;
  };
  medium: {
    url: string;
  };
  smalll: {
    url: string;
  };
  watch: {
    url: string;
  };
};
// 프로퍼티가 많아지면 중복 코드가 많아진다.
type Thumbnail = Record<
  "large" | "medium" | "small" | "watch",
  { url: string; size: number }
>;
// 1번재 타입 변수는 객체 프로퍼티의 키를 유니온으로 받고, 2번째 타입 변수는 키들의 value타입

Record타입 구현하기

type Record<K extends keyof any, V> = {
  [key in K]: V;
};

조건부 타입 기반의 유틸리티 타입 - Exclude, Extract, ReturnType

Exclude<T, U>

제외하다, 추방하다

T에서 U를 제거하는 타입

type A = Exclude<string | boolean, boolean>;
// A는 string | boolean에서 boolean 타입을 제거한 string타입으로 정의된다.

Exclude타입 구현하기

type Exclude<T, U> = T extends U ? never : T;
// 1단계
// Exclude<string, boolean>
// Exclude<boolean, boolean>

// 2단계
// string |
// never

// 최종적으로는 string | never(공집합이라 사라짐)
// -> string 타입이 된다.

// Extract<T, U>
// -> T에서 U를 추출하는 타입

Extract타입 구현하기

type Extract<T, U> = T extends U ? T : never;

ReturnType

함수의 반환값 타입을 추출하는 타입

예시

function funcA() {
  return "hello";
}

function funcB() {
  return 10;
}

type ReturnA = ReturnType<typeof funcA>;
type ReturnB 

ReturnType타입 구현하기

type ReturnType<T extends (...args: any) => any> = T extends (
  ...args: any
) => infer R
  ? R
  : never;

0개의 댓글