Exclude<T, U>는 TypeScript에서 union 타입에서 특정 값을 제외하기 위해 사용되는 유틸리티 타입입니다.
TypeScript에서는 타입을 다른 타입에서 편리하게 뺄 수 있는 방법이 없었습니다. 제너릭 API를 만들거나 리팩토링할 때 자주 "남은" 타입, 즉 금지된 값을 제외한 모든 타입을 얻어야 했습니다. 수동으로 union을 조작하는 대신 비슷한 인터페이스를 여러 개 유지해야 했습니다.
예를 들어, 'A | B | C'라는 타입이 있을 때 B를 제외한 타입을 얻고 싶다면 이 경우가 많습니다. 이는 복잡한 함수의 입력 매개변수를 구성하거나 허용된 값을 필터링하며 동적으로 타입을 생성할 때 필요한 경우가 많습니다.
Exclude는 이 문제를 해결합니다. 간단한 시그니쳐는 다음과 같습니다:
type Exclude<T, U> = T extends U ? never : T;
이는 T에서 U를 제외한 타입을 반환합니다.
예제:
type Status = 'draft' | 'published' | 'removed'; type UserVisibleStatus = Exclude<Status, 'removed'>; const visible: UserVisibleStatus = 'draft'; // OK
주요 특징:
Exclude를 일반 타입에 사용할 수 있나요, 아니면 union에서만 사용할 수 있나요?
만약 T가 union 타입이 아니더라도 U에 포함되면, Exclude는 여전히 작동하지만 결과는 never 또는 T가 될 수 있습니다. 이는 항상 직관적이지 않습니다.
Exclude<'a', 'a'> // 결과: never Exclude<'a', 'b'> // 결과: 'a'
Exclude가 객체 구조에서 타입의 모든 언급을 제거하나요?
아니요, Exclude는 타입의 중첩된 필드를 재귀적으로 통과하지 않으며, union의 최상위 레벨에서만 제외합니다.
Exclude는 인터페이스 및 객체 타입과 함께 어떻게 작동하나요?
그것은 전체 타입을 비교하며 개별 속성을 비교하지 않습니다. 따라서 다수의 인터페이스의 union에서 Exclude를 사용하면 U와 완전히 일치하는 것만 제거됩니다.
interface A { x: number }; interface B { y: string }; // Exclude<A|B, B>는 A를 반환합니다. (B가 완전히 일치함)
Exclude<UserRoles, 'admin'>를 통해 사용자의 역할을 검증했지만, Exclude가 중첩 구조에 적용되지 않음을 잊어버려 'admin:sub' 권한이 제외되지 않았습니다.
장점:
단점:
공용 API를 Exclude<Action, 'delete'>를 사용하여 위험한 작업을 제외함으로써 제한하는 경우입니다.
장점:
단점: