kakasoo

Omit type 정의하기 & Type level에서 as문 사용하기 본문

프로그래밍/TypeScript

Omit type 정의하기 & Type level에서 as문 사용하기

카카수(kakasoo) 2023. 2. 10. 00:01
반응형
interface Person {
  body: number;
  mind: boolean;
  soul: boolean;
}

type Zombie = MyOmit<Person, mind | soul>; // type Zombie = { body: number };

Person에서 mind | soul을 제외하면 body만 남는 걸 Zombie라고 정의할 수 있다고 해보자.

MyOmit은 방금 한 말을 타입으로 정의하는 방법으로, TypeScript에서 Utility type으로 이미 정의된 Omit과 동일하다.

Omit 타입을 구현하려면 아래처럼 사고를 확장해나가면 된다.

 

type MyOmit<T,K> = any;

 

가장 먼저 이 타입은 두 개의 타입 파라미터를 받는다고 정의할 수 있다.

 

type MyOmit<T, K extends keyof T> = any;

K는 무조건 T라는 타입 안에 정의된 프로퍼티들로만 구성되어 있어야 하기 때문에 K extends keyof T가 성립한다.

애초에 정의가 되어 있지 않다면 제외할 필요도 없이, 이미 없을 것이기 때문에, 존재하는 프로퍼티로만 구성되어야 한다.

따라서 keyof 연산자가 필요했다.

 

type MyOmit<T, K extends keyof T> = {
    [key in keyof T]: T[key];
};

다음 정의는, T에 있는 모든 키 ( = key ) 로 이루어져 있으며, 그 키에 대한 타입은 T[key]로 되어 있는 타입이다.

이 타입은 이미 T와 같다.

이제 이 타입에서 K와 일치하는 것들만 제거해주면 된다.

따라서, as문으로 타입 단언을 해줄 것인데, 아래와 같이, 필요없는 타입들을 걸러내주면 된다.

 

type MyOmit<T, K extends keyof T> = {
    [key in keyof T as key extends K ? never: key]: T[key];
};

key in keyof T는, as 즉 우측의 식과 동일하다.

우측의 식은 key extends K ? never: key 인데, key가 K에 포함된다면 제외해야 하므로 never이고 아니면 그대로 key를 반환한다.

never가 key인 값은 존재하지 않기 때문에 키의 타입이 무엇이든지 관계없이 T에서 제외됨을 의미한다.

즉 key는 T에서 K에 포함된 것들을 제외한 나머지 프로퍼티 이름을 의미한다.

 

type MyOmit<T, K extends keyof T> = {
  [key in Exclude<keyof T, K>]: T[key];
}

이미 정의된 Exclude를 사용한다면 이렇게도 설명할 수 있다.

Exclude는 어떻게 정의할 수 있을까?

 

 

Exclude은 왜 T extends U ? never : T 인가?

// Question : Exclude type을 정의하라 type question = any; TypeScript Utility type인 Exclude의 정의를 보면 T extends U ? never : T 라는 매우 생소한 표현이 등장한다. 아니, Exclude는 두번째 타입 파라미터로 받은 U를

kscodebase.tistory.com

 

반응형