이번에는 Type Script의 infer를 잘 이해해주세요.
19330 단어 TypeScripttech
어렵다
사용 기회는 적지만 개인은 React Query의 키 관리 등에서 이런 사용법을 자주 사용한다.
적극적이지 못하다
infer
는이해가 안되기 때문에하나하나분해해가며깊게이해하려고 하는것 같아요.export const QUERY_KEYS = ["users", "post", "comments"] as const;
export type Unpacked<T> = T extends { [K in keyof T]: infer U } ? U : never;
export type QueryKeysTypes = Unpacked<typeof QUERY_KEYS>;
const 결단
as const
이것은 const 결단이다.이를 설명하기 전에 위딩 리터럴 Types와 논 위딩 리터럴 Types를 전제로 이해할 필요가 있다.const로 변수를 정의할 때
hoge
의 유형은 "HOGE"
이다.const hoge = "HOGE";
// type hoge: "HOGE"
let sameHoge = hoge;
// type sameHoge: string
다른 변수에 대입하면sameHoge: string
.결론적으로 변수를 정의한 경우 기본값은 Widening Literal Types입니다.원래는 const로 형 정의를 내리면 Literal Types였지만, 이 안에는 상기 위드닝 Literal Types와 NonWidening Literal Types 두 가지가 은근히 존재한다.
스트링과'허지'의 한정형이 재대입을 통해 스트링을 확대한 것으로 보인다.반면 논위딩 리터럴 티페스는 아무래도 커지지 않는 리터럴 티페스를 뜻한다.
그렇다면 어떻게 하면 논위딩 리터럴 티페스로 만들 수 있을지에 대해 콘스트리졸브를 사용하면 변수를 선언하면서 유형의 확대를 억제할 수 있다.
const hoge = "HOGE" as const;
let sameHoge = hoge;
// type sameHoge: "HOGE"
// また他のオブジェクトに代入をしてもNonWidening Literal Typesであることがわかる
const obj = {
hoge, // "HOGE"
};
obj.hoge = "fuga"; // おこ
const결단은 당연히 배열과 대상에 적용되고readonly도 수여된다.따라서 그룹을 다시 대체할 수 없습니다.const hoge = ["HOGE"] as const;
// type hoge: readonly ["HOGE"]
hoge[1] = "huga"; // Tuple type 'readonly ["HOGE"]' of length '1' has no element at index '1'
readonly가 부여돼 재대입이 불가능해지자 리액트 프로젝트에서 더 적극적으로 활용하고자 한다.Conditional Types
Condiional Types는 세 연산자와 동일하게 쓸 수 있는 유형 정의의 조건 브랜치입니다.
쉽게 말해 T형이 땡땡이라면 이런 조건을 틀에 넣을 수 있다.
type IsNumber<T> = T extends number ? true : false;
type Hoge = IsNumber<"a">; // false
type Fuga = IsNumber<1>; // true
type Foo = IsNumber<boolean>; // false
키오브와 조합하면 이런 것도 할 수 있어요.
대상에 속성이 있으면, 대상의 값을 되돌려주고, 없으면 type 오류를 되돌려줍니다.
따라서 대상에 따라 유연하게 대응할 수 있고 타자를 방지할 수 있다.
const getValue = <T, U extends keyof T>(value: T, key: U): T[U] => {
return value[key];
};
const dog = {
name: "Taro",
age: 10,
};
const cat = {
name: "Jiro",
age: 3,
type: "hoge",
};
getValue(dog, "name");
// function getValue<{
// name: string;
// age: number;
// }, "name">(value: {
// name: string;
// age: number;
// }, key: "name"): string
getValue(dog, "type"); // Argument of type '"type"' is not assignable to parameter of type '"name" | "age"'.
getValue(cat, "type");
// function getValue<{
// name: string;
// age: number;
// type: string;
// }, "type">(value: {
// name: string;
// age: number;
// type: string;
// }, key: "type"): string
infer
직역하면 추론의 의미로 한마디로 형식을 추단해 낼 수 있다.
예를 들어 T에 id 속성이 있으면 id 유형을 반환합니다.
id 속성이 없으면never로 되돌아갈 수 있습니다.
type Id<T> = T extends { id: infer U } ? U : never;
또한 infer를 사용하는 장소는 condiional types의 extends의 조건 부분에 한정되어 있기 때문에 사용 방법으로 conditional types와 조합하여 사용한다.원래 코드를 풀다
그럼 최초의 코드를 풀자.
export const QUERY_KEYS = ["users", "post", "comments"] as const;
export type Unpacked<T> = T extends { [K in keyof T]: infer U } ? U : never;
export type QueryKeysTypes = Unpacked<typeof QUERY_KEYS>;
먼저 const 할당을 통해 스토리지를 Non Widening Literal Types로 설정합니다.이렇게 하면
QUERY_KEYS: readonly ["users", "post", "comments"]
.export const QUERY_KEYS = ["users", "post", "comments"] as const;
const 결단을 내리지 않았다면 단순했을 뿐string[]
.export const QUERY_KEYS = ["users", "post", "comments"];
// QUERY_KEYS: string[]
다음은 Unpacked
무엇을 하는지 봅시다.전체 이미지로서 T
[K in keyof T]
속성이 있으면 해당 유형이 반환됩니다.export type Unpacked<T> = T extends { [K in keyof T]: infer U } ? U : never;
그럼 이번 T는 뭘까요["users", "post", "comments"]
[K in keyof T][0]: 그럼 inferU는 "users"
[1]: 그러면 inferU는 "post"입니다.
[2]: 그럼 inferU는 "comments"
지렛대가 되다.또 네버는'있을 수 없는 유형'이지만 이번 코드의 특성상 [K in keyof T]는 존재하지 않기 때문에 네버에 들어가지 않는다.
마지막으로, 변수 QUERYKEYS 유형에서 정렬된 유형을 제거합니다.
export type QueryKeysTypes = Unpacked<typeof QUERY_KEYS>;
따라서QueryKeysTypes의 유형은 다음과 같다.type QueryKeysTypes = "users" | "post" | "comments";
총결산
infer를 사용하면 약간 빙빙 도는 유형 정의가 있을 수 있지만 실제 코드나 사용된 배열로 유형을 정의하는 것이 좋습니다.배열과 제작 유형을 동시에 제작할 수 있는 느낌.
많이 이해했으니까 업무적으로 적극적으로 활용하고 싶어요.
Reference
이 문제에 관하여(이번에는 Type Script의 infer를 잘 이해해주세요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/brachio_takumi/articles/464106a6a80eca8ab919텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)