매핑된 유형의 유형 추론: 토끼굴과 튀어나오는 기술
9444 단어 typescript
문제
다음과 같은 개체를 처리한다고 가정합니다.
const foobar = {
foo: ["foo"],
bar: ["bar", "bar"],
}
const boo = {
boo: ["boo", "boo", "boo"],
}
어떻게 입력하시겠습니까? 그들은 다음과 같이 특징지어지는 것 같습니다.
string
입니다. 그리고 항상 그렇듯이 우리는 논증 유형에 가능한 한 가장 강력한 제한과 추론을 부과하고자 합니다.
논의
단순화를 위해 다음
identity
함수를 생각해 봅시다.const result = identity({
foo: ["foo"],
bar: ["bar", "bar"],
});
// => result = {
// foo: ["foo"],
// bar: ["bar", "bar"],
// }
그런 다음 typescript가
result
의 유형을 확인하여 인수의 유형을 유추하는 방법을 볼 수 있습니다.사례 1: 녹화
간단한
Record
유형부터 시작하겠습니다.const identity1 = (arg: Record<string, string[]>) => arg;
이 경우
Record<string, string[]
객체만 얻습니다.이런 식으로. 우리는 "foo"와 "bar"가 교환되는 객체를 허용합니다.
Record
유형의 키 유형과 값 유형 간의 관계에 대한 제한이 없기 때문입니다.사례 2: 매핑된 유형
다음으로 매핑된 유형을 시도합니다.
const identity2 = (arg: {
[T in string]: T[],
}) => arg;
좋은 것 같죠? 그러나 우리는 이것을 얻습니다:
이 유형은 기본적으로 마지막 유형과 동일합니다.
키와 값 유형 간의 관계를
[T in string]: T[]
로 지정했습니다! 어디로 갔습니까? 대신에 우리는 무엇을 해야 합니까?대답
해결책은 다음과 같습니다.
function identity3<U extends string>(arg: {
[T in U]: T[]
}) {
return arg;
}
이 방법으로 typescript는 인수의 유형을 매우 구체적으로 유추할 수 있습니다.
불법 개체를 허용하지 않습니다.
해설
그렇다면
identity2
와 identity3
의 차이점은 무엇입니까? 먼저 매핑된 유형이 무엇인지 기억해 봅시다.https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
다음과 같이 말합니다.
A mapped type is a generic type which uses a union of PropertyKeys (frequently created via a keyof) to iterate through keys to create a type:
즉,
[T in X]
, X
는 합집합이거나 "foo" | "bar" | "boo"
와 같아야 합니다.이제
identity2
를 어떻게 정의했는지 기억해 봅시다.const identity2 = (arg: {
[T in string]: T[],
}) => arg;
우리는
string
를 X
에 넣고 타이프스크립트가 허용했습니다. 이것은 string
가 일종의 합집합이라는 것을 의미합니다.그러나 노동 조합으로서
string
는 무엇입니까? 우리는 그것을 우리가 만들 수 있는 모든 문자열 리터럴의 합집합 또는 무제한의 문자열 모음으로 생각할 수 있습니다.따라서
identity2
는 이러한 컬렉션의 모든 요소 T
를 T[]
에 매핑하도록 정의되지만 TypeScript는 우리에게 가능하다고 생각하지 않습니다. 그런 다음 유형은 일반 레코드와 같은 것으로 돌아갑니다.그렇다면
identity3
는 어떻습니까? 여기서 해결책은 무엇입니까?function identity3<U extends string>(arg: {
[T in U]: T[]
}) {
return arg;
}
U extends string
대신 string
를 사용합니다. 이 방법U
은 제한된 수의 문자열 리터럴이 있는 string
의 하위 집합으로 간주될 수 있으며 유형은 유효한 매핑 유형으로 간주됩니다!{ foo: ["foo"], bar: ["bar"] }
를 함수에 전달하는 예에서 "foo" | "bar"
는 U
와 일치하고 모든 항목은 정의된 대로 T[]
에 매핑된 것으로 확인됩니다.후기
이 기술이 실제 시나리오에서 어떻게 사용되는지에 관심이 있다면 Deno + Cloudflare Workers로 웹 API를 구축하기 위한 프레임워크인 제가 진행 중인 작업의 소스 코드를 참조하세요.
https://github.com/hasundue/flash
친절하게 읽어주셔서 감사합니다!
참조
Reference
이 문제에 관하여(매핑된 유형의 유형 추론: 토끼굴과 튀어나오는 기술), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hasundue/type-inference-in-mapped-types-a-rabbit-hole-and-a-technique-to-jump-out-5ci8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)