[Daily morning study] TypeScript์˜ Utility Types (Partial, Pick, Omit ๋“ฑ)

#daily morning study

Image


TypeScript์˜ Utility Types

TypeScript๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋”์šฑ ํšจ์œจ์ ์œผ๋กœ ์ฝ”๋“œ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋•๋Š” ์—ฌ๋Ÿฌ ๋‹ค์–‘ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ€์ด๋“œ์—์„œ๋Š” Partial, Pick, Omit, Record, Exclude, Extract์™€ ๊ฐ™์€ ์ฃผ์š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

1. Partial

Partial<T> ํƒ€์ž…์€ ์ฃผ์–ด์ง„ ํƒ€์ž… T์˜ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋ฅผ ์„ ํƒ์ (optional)์œผ๋กœ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ์ด ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ํŠน์ • ๊ฐ์ฒด์˜ ์ผ๋ถ€ ํ”„๋กœํผํ‹ฐ๋งŒ์„ ์—…๋ฐ์ดํŠธํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ

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

const updateUser = (id: number, userUpdates: Partial<User>) => {
  // ์—…๋ฐ์ดํŠธ ๋กœ์ง
};

updateUser(1, { name: "์ƒˆ ์ด๋ฆ„" });

์œ„ ์ฝ”๋“œ์—์„œ userUpdates๋Š” User ์ธํ„ฐํŽ˜์ด์Šค์˜ ์„ ํƒ์ ์ธ ํ”„๋กœํผํ‹ฐ๋“ค๋งŒ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. Pick<T, K>

Pick<T, K> ํƒ€์ž…์€ ์ฃผ์–ด์ง„ ํƒ€์ž… T์—์„œ ํŠน์ • ํ”„๋กœํผํ‹ฐ K๋งŒ ์„ ํƒํ•˜์—ฌ ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ ํฐ ๊ฐ์ฒด์—์„œ ์ผ๋ถ€ ํ”„๋กœํผํ‹ฐ๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ

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

type UserPreview = Pick<User, "id" | "name">;

const user1: UserPreview = {
  id: 1,
  name: "์‚ฌ์šฉ์ž1",
};

์œ„ ์˜ˆ์‹œ์—์„œ๋Š” UserPreview ํƒ€์ž…์ด User ํƒ€์ž…์—์„œ id์™€ name ํ”„๋กœํผํ‹ฐ๋งŒ ์„ ํƒํ•œ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.

3. Omit<T, K>

Omit<T, K> ํƒ€์ž…์€ Pick๊ณผ๋Š” ๋ฐ˜๋Œ€๋กœ, ํŠน์ • ํ”„๋กœํผํ‹ฐ K๋ฅผ ์ œ์™ธํ•œ ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์˜ˆ์‹œ

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

type UserWithoutEmail = Omit<User, "email">;

const user2: UserWithoutEmail = {
  id: 2,
  name: "์‚ฌ์šฉ์ž2",
};

์œ„ ์˜ˆ์‹œ์—์„œ๋Š” UserWithoutEmail ํƒ€์ž…์ด User ํƒ€์ž…์—์„œ email ํ”„๋กœํผํ‹ฐ๋ฅผ ์ œ์™ธํ•œ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.

4. Record<K, T>

Record<K, T> ํƒ€์ž…์€ ์ฃผ์–ด์ง„ ํ‚ค K์™€ ๊ฐ’ T๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด ํƒ€์ž…์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’์ด ๋™์ผํ•œ ํƒ€์ž…์ผ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ

type UserRoles = "admin" | "editor" | "viewer";
type RolePermissions = Record<UserRoles, string[]>;

const permissions: RolePermissions = {
  admin: ["read", "write", "delete"],
  editor: ["read", "write"],
  viewer: ["read"],
};

์œ„ ์ฝ”๋“œ์—์„œ๋Š” UserRoles ํƒ€์ž…์˜ ๊ฐ ์—ญํ• ์— ๋Œ€ํ•ด ๊ถŒํ•œ์„ ์ •์˜ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

5. Exclude<T, U>

Exclude<T, U>๋Š” ์ฃผ์–ด์ง„ ํƒ€์ž… T์—์„œ U์— ํ•ด๋‹นํ•˜๋Š” ํƒ€์ž…์„ ์ œ์™ธํ•œ ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ

type AllNumbers = number | string | boolean;
type OnlyNumbers = Exclude<AllNumbers, string | boolean>; // number๋งŒ ๋‚จ์Šต๋‹ˆ๋‹ค.

์œ„ ์ฝ”๋“œ์—์„œ OnlyNumbers๋Š” number ํƒ€์ž…๋งŒ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

6. Extract<T, U>

Extract<T, U>๋Š” ์ฃผ์–ด์ง„ ํƒ€์ž… T ์ค‘์—์„œ U์˜ ์„œ๋ธŒํƒ€์ž…์„ ์ถ”์ถœํ•˜์—ฌ ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ

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

์œ„ ์ฝ”๋“œ์—์„œ StringOrNumber๋Š” string๊ณผ number ํƒ€์ž…๋งŒ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

๋งˆ๋ฌด๋ฆฌ

TypeScript์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…๋“ค์€ ํƒ€์ž… ๊ด€๋ฆฌ๋ฅผ ํ›จ์”ฌ ์ˆ˜์›”ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ์ฃผ๋ฉฐ, ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ๊ธฐ์—ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…๋“ค์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ๋”์šฑ ํšจ์œจ์ ์ด๊ณ  ์•ˆ์ „ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์™€ ํ•จ๊ป˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๋ฉฐ ์ตํ˜€๋ณด์„ธ์š”!