상용구 없이 동일한 TypeScript 열거형 간의 매핑
9347 단어 typescript
동일한 구성원을 포함하는 두 개의 열거형이 있지만 TS는 이들이 호환되는지 인식하지 못합니다. 이제 저는 사람들이 문제를 해결하기 위해 활용하는 세 가지 주요 패턴을 봅니다.
IDC 접근 방식: 어디서나 캐스팅합니다. 이것은 가장 쉽지만 enum 캐스트를 사용하면 거의 모든 작업을 수행할 수 있으므로 위험합니다.
순수주의자: "그들은 다른 것을 나타내기"때문에 유형이 다르므로 유사성을 무시하고 매퍼 함수(또는 개체)를 만들고 필요한 경우 사용합니다.
이것은 확실히 매우 안전하지만 많은 유지 관리 오버헤드와 코드(번들) 크기를 추가합니다.
중간 지점: 함수를 생성하지만 내부에 캐스트합니다.
이것은 한 번만 캐스트하기 때문에 종이에 접근하는 것보다 더 좋아 보이지만 실제로는 여전히 동일한 위험에 노출되기 쉽습니다. 두 개의 열거형이 어떤 지점에서든 분기되면 TS에서 단일 경고를 받지 않습니다.
상용구가 없는 유형 안전
#3의 순도와 번들 크기를 유지하면서 접근 방식 #2의 유형 안전성을 어떻게든 얻을 수 있을까? 우리는 할 수 있습니다.
JS 수준에서 이 세 번째 접근 방식은 사소하며 매퍼 기능은 기본적으로
x => x
입니다.따라서 이제 동일한 열거형 사이에서만 매핑할 수 있도록 TS 제약 조건을 추가하는 것이 "단지"문제입니다.
구현
핵심
내 현재 솔루션은 단순성을 위해 대칭(동일한 키 및 값) 열거형으로만 작동하지만 매우 잘 확장될 수 있습니다. 먼저 대칭 열거형이 무엇인지 정의해 보겠습니다.
type SymmetricalEnum<TEnum> = {
[key in keyof TEnum]: key;
};
그런 다음 트릭이 있습니다. 우리는 매핑의 결과 값이 무엇인지 정의할 수 있습니다. 이것은 기본적으로 모든 이점과 함께 TS 메타 언어 수준에서 매핑을 수행하는 것입니다.
type MapperResult<
TSourceEnumObj,
TDestEnumObj extends SymmetricalEnum<TSourceEnumObj>,
TSourceValue extends keyof TSourceEnumObj
> = TDestEnumObj extends { [key in TSourceValue]: infer TResult } ? TResult : never;
3개의 일반 인수가 있습니다.
유형 수준에서 매핑이 필요한 경우 위의 내용을 자체적으로 사용할 수 있습니다. 예를 들어 이 마법을 참조하세요.
호환되지 않는 열거형은 거부됩니다. 다음과 같은 경우에도 매우 명확한 오류 메시지가 표시됩니다.
매퍼 함수 만들기
이제 이 마법을 활용하여 매퍼 함수를 자동 생성하는 고차 함수를 만들 준비가 되었습니다.
const createEnumMapperFunction =
<TSourceEnumObj, TDestEnumObj extends SymmetricalEnum<TSourceEnumObj>>(from: TSourceEnumObj, to: TDestEnumObj) =>
<TInput extends keyof TSourceEnumObj>(value: TInput) =>
value as MapperResult<TSourceEnumObj, TDestEnumObj, TInput>;
포착한 오류를 포함하여 여기에서 작동 중인 것을 볼 수 있습니다.
그리고 이것이 다입니다! 이제 모든 switch 문을
createEnumMapperFunction
에 대한 호출로 바꾸거나 캐스트를 위와 같은 유형 안전 버전으로 바꿀 수 있습니다. 비대칭 열거형 또는 기타 사례에 대한 지원을 추가하는 것과 같이 필요에 따라 자유롭게 조정할 수 있습니다.최종 코드
StackOverflow 키보드가 있는 경우
전체 코드는 다음과 같습니다TS Playground with examples.
type SymmetricalEnum<TEnum> = {
[key in keyof TEnum]: key;
};
type MapperResult<
TSourceEnumObj,
TDestEnumObj extends SymmetricalEnum<TSourceEnumObj>,
TSourceValue extends keyof TSourceEnumObj
> = TDestEnumObj extends { [key in TSourceValue]: infer TResult } ? TResult : never;
const createEnumMapperFunction =
<TSourceEnumObj, TDestEnumObj extends SymmetricalEnum<TSourceEnumObj>>(from: TSourceEnumObj, to: TDestEnumObj) =>
<TInput extends keyof TSourceEnumObj>(value: TInput) =>
value as MapperResult<TSourceEnumObj, TDestEnumObj, TInput>;
언젠가 이 정보가 도움이 되기를 바랍니다. 그렇게 했다면 댓글로 알려주고 개선된 버전을 만들었다면 저도 알고 싶습니다.
Reference
이 문제에 관하여(상용구 없이 동일한 TypeScript 열거형 간의 매핑), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/marcelltoth/mapping-between-identical-typescript-enums-without-the-boilerplate-5b28텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)