SW Engineering•2025.11.27

Omit은 Props를 타입핑할 때 유용할 수 있습니다. 구현을 기본 요소와 연결할 수 있기 때문입니다.UserSelect 컴포넌트를 만들 수 있습니다:SelectProps의 모든 필드를 다시 선언(그리고 복사)할 필요가 없다는 것과, 자동으로 서로 동기화된다는 것입니다. 의존성은 의도적입니다: {...props}를 Select에 spread하고 있으므로, 타입도 이미 그것을 선언하고 있으며, Select에 필드를 추가하면 UserSelect도 그 이점을 누릴 수 있습니다.SelectProps가 너무 복잡해지기 전까지는요.Select에 새로운 기능을 추가해봅시다: 사용자가 현재 값을 선택 해제할 수 있게 해주는 clearable prop입니다. 그런 일이 발생하면, onChange를 null로 트리거하고 싶을 겁니다. 타입의 첫 번째 초안은 다음과 같을 수 있습니다:Select 사용이 에러가 됩니다. 왜냐하면 그들의 onChange 핸들러들이 null을 처리하지 않기 때문입니다. 이것은 좋지 않습니다. 왜냐하면 그들은 런타임에 null을 받지 않을 것이기 때문입니다. 명확하게 clearable이 아니니까요.clearable을 전달하면, onChange가 null을 받을 수 있습니다. 그렇지 않으면 받지 않습니다". Discriminated Unions이 우리를 도와줄 수 있습니다:clearable 플래그에서 union을 구분할 수 있습니다: 만약 true로 전달되면, onChange는 false로 전달되거나 전혀 전달되지 않을 때와 다른 구조를 갖게 됩니다. BaseSelectProps로의 추출은 단지 union의 두 부분에서 동일한 타입들을 반복하는 것을 피하기 위해 수행되었습니다.clearable 기능은 타입 수준에서도 역호환성을 갖게 되므로, 배포할 준비가 되어야 합니다. 그런데 놀랍게도, CI에서 우리의 UserSelect 컴포넌트에 에러를 발견합니다. 다음과 같은 것입니다:Omit으로 타입을 구성하고 있었고, 이전에는 작동했거든요. 🤔 그래서 뭐가 바뀌었을까요?UserSelectProps가 이제 무엇으로 확장되는지 검사했을 때 더 이해가 되기 시작했습니다:Omit을 추가하는 것은 기본적으로 모든 것을 "확장"했습니다. 확실히 Omit의 버그처럼 보이지만, 아닙니다. 이것은 의도된 동작입니다.Omit은 각 union을 개별적으로 보지 않습니다 (이것은 distributive하지 않습니다). 전체 union을 취급하고 모든 멤버를 하나씩 매핑합니다. Ryan Cavanaugh가 이슈 댓글 중 하나에서 말했듯이, Omit의 모든 가능한 정의는 특정 트레이드오프를 가지고 있으며, 그들은 최고의 일반적인 적합이라고 생각하는 것을 선택했습니다.Omit 헬퍼를 작성할 수 있어야 하고, 운 좋게도, 우리는 Distributive Conditional Types보다 더 멀리 볼 필요가 없습니다.T extends any ? ... : never라고 말하는 타입을 본 적이 있고 궁금해한 적이 있나요: 왜 그렇게 할까요? 명백하게, 모든 것이 any를 확장합니다 - 이것은 TypeScript의 top 타입입니다.Omit을 호출하여 우리의 union과 더 잘 작동하는 Omit 헬퍼 타입을 만들 수 있습니다:UserSelectProps에 적용하면 어떻게 되는지 봅시다:Omit이 우리의 union 타입의 각 부분에 적용되며, 우리의 UserSelect는 이제 clearable 기능으로부터 암묵적으로 이점을 누릴 것입니다.🎉DistributiveOmit 솔루션에 코딩한 또 다른 이점이 있습니다. 일반적인 Omit은 이것을 가지고 있지 않습니다:Omit의 타입 시그니처를 보면:K 타입 파라미터에 상한이 없다는 것을 볼 수 있습니다 (keyof any는 단지 string | number | symbol로 확장됩니다). 이것은 객체에 실제로 존재하지 않는 키를 전달할 수 있다는 의미입니다. 이것은 실제로는 해롭지 않습니다. 거기에 없는 것을 생략하는 것은 아무것도 변경하지 않기 때문입니다. 하지만 이것은 나를 놀라게 했습니다. DistributiveOmit으로 전환했을 때 (K extends keyof T를 사용), TypeScript는 갑자기 5개의 키를 생략하고 있는 곳들을 플래그했습니다. 심지어 그 중 2개는 더 이상 존재하지 않았는데요.아직 댓글이 없습니다.
첫 번째 댓글을 작성해보세요!

TypeScript 7 진행 상황 - 2025년 12월
Inkyu Oh • SW Engineering

언어의 환상: 지시어(directive)의 정체
Inkyu Oh • Front-End

Dead Framework Theory
Inkyu Oh • Front-End