[TypeScript] 유틸리티 타입(Utility Types)

    Utility Types

     

    📌 keyof

    keyof 연산자는 객체 타입에서 객체의 키 값들로 숫자/문자열 리터럴 유니언을 생성한다.

     

    // keyof
    
    interface User {
      id: number;
      name: string;
      age: number;
      gender: "m" | "f";
    }
    
    type UserKey = keyof User; // 'id' | 'name' | 'age' | 'gender'
    
    const uk:UserKey = "name";

     

    📌 Partial<T>

    Partial<T>는, <T>의 모든 프로퍼티를 옵션(선택적)으로 바꿔준다.

    // Partial<T>
    
    interface User {
      id: number;
      name: string;
      age: number;
      gender: "m" | "f";
    }
    
    // interface User {
    //   id?: number;
    //   name?: string;
    //   age?: number;
    //   gender?: "m" | "f";
    // }
    
    
    
    let admin: Partial<User> = {
      id: 1,
      name: "Bob"
      // hobby: "Reading" -> Error!
    };

    단, User에 없는 프로퍼티를 사용하면 에러가 발생한다.

     

     

    📌 Required<T>

    Partial<T>반대로, Required<T>는 <T>의 모든 프로퍼티를 필수로 바꿔 준다.

    // Required<T>
    
    interface User {
      id: number;
      name: string;
      age?: number;
    }
    
    let admin: Required<User> = {
      id: 1,
      name: "Bob"
    };
    
    // -> Error: age도 필수 프로퍼티가 되어서, 넣어줘야 한다..

     

    📌 Readonly<T>

    <T>를 읽기 전용으로 바꿔 준다.

    // Readonly<T>
    
    interface User {
      id: number;
      name: string;
      age?: number;
    }
    
    let admin: Readonly<User> = {
      id: 1,
      name: "Bob"
    };
    
    // admin.age = 12; -> Error

     

    📌 Record<K,T>

    두 개의 제네릭 타입을 받는다. ✅ K(key 값의 타입), T(value 값의 타입)

    // Record<K,T> 예제1
    
    // interface Score {
    //   "1" : "A" | "B" | "C" | "D" ;
    //   "2" : "A" | "B" | "C" | "D" ;
    //   "3" : "A" | "B" | "C" | "D" ;
    //   "4" : "A" | "B" | "C" | "D" ;
    // }
    
    const score: Record<"1" | "2" | "3" | "4", "A" | "B" | "C" | "D"> = {
      1: "A",
      2: "B",
      3: "C",
      4: "A"
    }
    
    type Grade = "1" | "2" | "3" | "4";
    type Score = "A" | "B" | "C" | "D";
    
    const score2: Record<Grade, Score> = {
      1: "A",
      2: "B",
      3: "C",
      4: "A"
    }
    // Record<K,T> 예제2
    
    interface User {
      id:number;
      name: string;
      age: number;
    }
    
    function isValid(user:User) {
      const result:Record<keyof User, boolean> = {
        id : user.id > 0,
        name : user.name !== '',
        age : user.age > 0
      }
    
      return result;
    }

     

    📌 Pick<T,K>

    T(Type)에서, K(특정 프로퍼티)를 선택하여 가져올 수 있다.

    // Pick<T, K>
    
    interface User {
      id: number;
      name: string;
      age: number;
      gender: "M" | "W";
    }
    
    const admin: Pick<User, 'id' | 'name'> = {
      id: 0,
      name: "Bob",
    }
    
    // User에서 id와 name만 가져와서 사용할 수 있다.

     

    📌 Omit<T, K>

    Omit<T>을 쓰면, T(Type)에서 K(특정 프로퍼티)를 생략하고 쓸 수 있다. ↔ Pick<T,K>

    // Omit<T, K>
    
    interface User {
      id: number;
      name: string;
      age: number;
      gender: "M" | "W";
    }
    
    const admin: Omit<User, 'age' | 'gender'> = {
      id: 0,
      name: "Bob",
    }
    
    // User에서 id와 name만 가져와서 사용할 수 있다.

     

    📌 Exclude<T1, T2>, NonNullable<T>

    Exclude<T1, T2>은 T1(Type1)에서 T2(Type2)를 제외하고 사용하는 방식으로,
    프로퍼티를 제거하는 Omit<T>와는 다르다. ( Exclude는 타입을 제거)

     

    NonNullable<T>는 <T>에서 nullundefined를 제외한 타입을 생성한다.

    // Exclude<T1, T2>
    
    type T1 = string | number | boolean;
    type T2 = Exclude<T1, number | string>;
    
    
    // NonNullable(Type)
    
    type T3 = string | null | undefined | void;
    type T4 = NonNullable<T3>


    🚀 참고

    댓글