TypeScript 의 Omit type 은 이상하다.

Universe·2023년 8월 8일
1

서론

저는 타입스크립트를 개발한 개발자 분들을 굉장히 존경합니다.
귀여운 타입스크립트는 자바스크립트 개발자의 삶의 질을 향상시켜주는
아주 고마운 존재임에 틀림없습니다.
그러한 사례 중 하나가 바로 유틸리티 타입인데,
그 중 Omit 타입의 의문점에 대해 생긴 의문과 나름의 해석을 서술하고자 합니다.

예시

예시를 위해 Post 라는 타입을 하나 정의해봤습니다.

type Post = {
  id: number;
  title: string;
  createdAt: Date;
  username: string;
  content: string;
  likesCount: number;
  likes: string[];
  commentsCount:number;
  comments: Comment[];
}

간단한 Post 타입입니다.

그런데, 게시글 목록 같은 구현사항을 구현할 때,
우리는 모든 데이터가 필요하지는 않습니다.
필요한 데이터는 아래와 같습니다.

type PostMetaData = {
  id: number;
  title: string;
  createdAt: Date;
  username: string;
  likesCount: number;
  commentsCount: number;
}

구현사항에 따라 조금 차이가 있을 수 있겠지만,
게시글 목록에서 실제 컨텐츠나 댓글, 좋아요를 누른 유저들을 볼 필요가 없습니다.
게시글이 많아지면 많아질수록 위의 속성들은 많은 데이터를 필요로 하기 때문에
최적화에 불리합니다. 그래서 목록에서 보여줄 값들만 간소화해서 받아옵니다.
친절하고 멋진 우리의 백엔드 개발자 분들은 목록을 위한 간소화 된 데이터를 보내주실 겁니다.

불편합니다.
PostMetaData 라는 type 은 필수적으로 필요하지만,
만약 필요한 데이터가 훨씬 많아진다면 일일히 타입을 지정해 주어야 하는 번거로움이 있습니다.
너무 피곤해서 실수할지도 모릅니다.

Pick

우리의 친절한 타입스크립트 개발자 분들은 이러한 불편을 두고보지 않습니다.

type PostMetaData = Pick<
    Post,
    "id" | "title" | "createdAt" | "username" | "likesCount" | "commentsCount"
  >;

이런식으로 Pick 키워드를 사용하면 주어진 타입에서 특정 프로퍼티만 선택하여 새로운 타입
만들 수 있습니다.
자동완성 기능도 지원합니다!

휴먼에러를 방지할 수 있을 뿐 아니라 '주어진 타입'을 가져와 쓰는 느낌이기 때문에
마치 상속하듯 사용할 수 있습니다.

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

Pick 은 위와 같이 구현되어 있습니다.
T는 '주어진 타입'을, K는 '주어진 타입에서 선택할 프로퍼티 키의 집합' 을 의미합니다.

Omit

그런데 위의 예시에서는 Pick 보다는 Omit 이 조금 더 편해보입니다.
9개의 속성 중 6개가 필요하다면, 나머지 3개를 빼주는 편이 조금 더 타자를 덜 칠 수 있습니다.

type PostMetaData = Omit<Post, "contents" | "like" | "comments">

아주 보기 좋습니다!
Omit 키워드를 사용하면 Pick 키워드와는 반대로 주어진 타입에서 몇몇 속성을 제거한 타입
만들 수 있습니다.

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

Omit 은 위와 같이 구현되어 있습니다.

🤔

뭔가 잘못된 점이 있습니다.
아주 단단히 잘못됐다고 봐도 무방합니다.

type PostMetaData = Omit<Post, "contents" | "like" | "comments">

제 Post 타입에 contents 라는 속성은 없습니다. content 라는 속성만 있어요.
위의 타입은 평소의 타입스크립트 처럼 content 의 오류가 아닐까요? 라고 물어봐 주지도 않습니다.
Omit이 적용된 PostMetaData 타입은 문법상 전혀 문제가 없습니다.

Pick이 자동완성을 지원하는 것에 반해 Omit은 자동완성을 지원하지 않을 뿐더러
'주어진 타입'의 속성에 해당하는 key 이름이 아니더라도 오류로 판단하지 않습니다.
Omit의 구현사항을 보면<T, K extends keyof any> 라는 부분을 확인할 수 있는데,
'주어진 타입'과는 상관없이 key 값의 형태를 띄고있다면 OK 라는 의미로 해석할 수 있습니다.
가장 큰 문제는 K가 T의 키 중 하나임을 보장할 수 없다는 점입니다.
Pick의 <T, K extends keyof T> 와는 사뭇 다른 느낌입니다.

StrictOmit

마음에 들지 않으니 직접 Omit을 구현해봅니다.
기존 구현사항보다 '엄격한' Omit 이라는 의미로 StrictOmit 이 좋겠네요.

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

T는 '주어진 타입'을 의미합니다.
K는 T의 키 중 일부를 나타내며, 제외할 키의 목록입니다.
[P in Exclude<keyof T, K>]는 순회하면서 T의 키 중 K에 속하지 않는 키를 추출해
새로운 타입을 생성합니다.
T[P]는 각 키 P에 해당하는 타입을 가져옵니다.

StrictOmit 타입은 '주어진 타입'의 키를 상정하고 있으므로,

자동완성을 지원할 뿐 아니라 평소처럼 친절하게 오타라고 알려주고 있습니다.

그럼 왜 ?

Omit의 구현사항을 보면

  • Construct a type with the properties of T except for those in type K.

라는 주석이 달려있습니다.
해석하자면 "K의 속성을 제외한 T의 속성을 가진 타입을 구성합니다" 라는 의미입니다.

  • From T, pick a set of properties whose keys are in the union K

"T에서, K의 유니온 타입에 해당하는 속성의 집합을 선택합니다" 와 대비되는 느낌입니다.

하지만, Omit 키워드를 사용하는 예시나 목적, 그리고 Pick 키워드와 대비되는 역할을
한다는 점을 미루어 보면 조금 이상합니다.

회의록 이슈
개발자 코멘트

(레퍼런스에 도움을 주신 '델'님 정말정말 감사합니다 🥳)

2019년 4월 3일자 회의로 Omit의 구현사항은 수정하지 않기로 했다고 합니다.
개발자 분의 자세한 코멘트는 위와 같습니다.
요약하자면 "이런 엄격한 버전의 구현은 업스트림을 강요하기 때문에 하지 않았고,
다른 이름으로 (예를들면 OmitStrict) 추가하는 것도 별로 바람직 하다고 생각하지 않으며,
추가하더라도 누군가는 좋아하지 않을거야." 라는 의미 정도로 해석됩니다.

추가로 보면 재미있는 이슈
위의 이슈 뿐 아니라, 이슈를 제기한 개발자들이 굉장히 많습니다.
이슈를 모두 읽어볼 수는 없었지만, 주로
"타입스크립트는 역사적으로 항상 엄격한 버전으로 예제를 보여줬는데 이제와서 왜?"
라는 의견이 대다수 입니다.
해당 이슈는 '이미 배포가 끝나서 고칠 수 없다' 로 결론지었다고 합니다.

결론

저는 "엄격한 버전으로 수정하는 쪽이 조금 더 좋았을 것 같다" 라는 의견입니다.
자동완성이 안된다- 의 문제를 차치하더라도 "K가 T의 키 중 하나임을 보장할 수 없다"
라는 건 정말 큰 문제라고 생각하기 때문입니다.

그럼에도 불구하고 개발자 분들의 결정은 존중합니다.
"무려 마이크로 소프트에서 개발하시는 분들이시니까-" 같은 단순한 이유가 아니라
팀 내부적인 회의를 통해 결정된 내용이기 때문입니다.
그리고 결정된 내용이 불합리하거나 이해할 수 없는 것도 아니니까요.
저는 아직 찾지 못했지만 특정 프로젝트나 사용 사례에 따라서 유연한 버전이
조금 더 나은 구현방식일지도 모릅니다.

의견은 주관적일 수 있으니까요.
실제로 당시에 정말 많은 개발자들이 주관적인 의견으로 토론이 이루어졌습니다.
이런 건설적인 토론과 공유 문화가 있기 때문에
오늘도, 내일도 새로운 기술들이 나오고 멋진 소프트웨어가 개발되는게 아닐까 생각해봅니다.

profile
Always, we are friend 🧡

0개의 댓글