TypeScript 유형 정의의 ○○?△△: 네버가 뭐예요?
10213 단어 TypeScript
type Foo<T> = T extends Bar ? Hoge : Fuga;
이 자체는 x ? y : z
연산자가 있는 언어를 터치하는 사람에게 비교적 직관적인 이해이다. 유니버설Foo<T>
의 형 매개 변수T
에 제공된 형 계승Bar
이라면Hoge
, 그렇지 않으면Fuga
이다."그럴 거야"라고 먼저 말하자 나는 애초에 그것마저'어?? 그럼
Hoge
이나 Fuga
라고 쓰면 되지 않겠니?그렇게 생각하지만 더 혼란스러운 것은 다음과 같은 기법이다.type Foo<T> = T extends Bar ? Hoge : never;
가까스로 조건에 대한 의견 차이never
...?뭘 위해서...?내 생각엔never
'불가능한 값의 유형'을 이해했기 때문에'T가 Bar Hoge라면 그렇지 않으면 불가능'은 무슨 뜻??그리고드디어 뜻과 빈번한 패턴을 깨달았기 때문에 오늘은 그 내용에 대해 설명하고 싶다일.
오프닝: 원래 조건형을 사용한다는 뜻은? 「え???じゃあ Hoge とか Fuga とか直接書けばよくない??」
표지인데 원래type
선언은 언제 사용했을까요?type
선언은 이미 존재하는 유형의 이름을 지정하거나 존재하는 유형과 비슷한 다른 유형을 정의하는 데 사용됩니다.// union 型 Piyo を定義している感覚になるが、
// TypeScript においては Hoge | Fuga で既に型として成立しており
// Piyo はその別名をつけているに過ぎない
type Piyo = Hoge | Fuga;
또 interface
선언도 대체적으로 비슷한 목적이다.// { bar: string } と直接書くことができるが、
// 何度も書くのは煩わしいし意図も伝えづらくなるため
// インターフェースに名前を与えて使いまわすことができる
interface Foo {
bar: string
}
즉, TypeScript의 형 선언은 기본적으로 "기존 형을 모두 열심히 쓰면 번거롭고 보수성과 가독성도 좋지 않기 때문에 이름을 붙이면 잘 할 수 있다"는 것이다.
이게 함수랑 방법이랑 생각이 비슷하죠?이렇게 되면 선언에서 조건의 불일치를 사용할 수 있는 의미와 장점도 쉽게 이해할 수 있겠지?
예를 들어 다음과 같은 장점ReturnType<T>
은 "이미 함수를 정의했고 이 반환값을 사용하는 유형의 의도가 있으면 반환값의 유형을 직접 쓸 수도 있지만 기존 함수의 이름ReturnType<typeof doSomething>
을 사용하는 의도가 더욱 명확하고 반환값의 유형이 길어도 군더더기가 없다"는 것이다.
모드 1: infer로 금형을 꺼낼 때 infer
를 사용하여 몰드를 체크 아웃할 때 항상 실제 조건(또는 항상 실제 조건)을 사용하는 경우가 있습니다.이것은 흔히 볼 수 있는 모델이다.
예를 들다.// 型パラメータに与えた関数型の戻り値の型を取り出す型 ReturnType<T> を定義。
// ReturnType<(s: string) => number> とすると number になる。
// 既に定義されている関数を元にその戻り値の型を表したいときに使う(そのまんまの説明ですが…)
type ReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer R ? R : never;
뭐가 엉망진창이지만 매개 변수 부분을 숨겨서 읽으면 이렇게 돼요.type ReturnType<T extends (■■) => any>
= T extends (■■) => infer R ? R : never;
형 구속조건은 T extends (■■) => any
이므로 "T
은 함수형", T extends (■■) => infer R ? R : never
은T
이 함수형이면 반환값의 형을 R
R
으로 하고 그렇지 않으면 never
(불가능)으로 합니다.
재형제약 때extends (■■) => any
,'되지 않을 때'는'불가능'이기 때문에 실질? R
만 사용하기 때문에: never
.
그럼 왜 조건을 붙여요?이것은 infer R
에서 반환 값 부분의 유형을 형 변수로 꺼내려고 하기 때문이다.
이처럼'형 변수 중infer
추출형의 일부분'을 위해 조건형을 사용하는 경우가 빈번하다.
또 아까의 예는 처음부터 T
에게만 함수형을 전달하려고 했다.유형 제약을 더하면 전달 함수형 이외의 경우 컴파일 오류가 발생할 수 있지만 유형 제약이 없더라도 이 경우'조건 불충족'never
으로 인해 사용할 수 없기 때문에 유형 제약이 없어도 실용적일 수 있다.type ReturnType<T> = T extends (...args: any) => infer R ? R : never;
앞의 예는'항상 조건이 성립된 상황'이고 뒤의 예는'조건이 성립된 상황만이 구상할 수 있는 상황'이다.
또한 실제ReturnType<T>
는 표준 라이브러리에서 정의된 것으로 다음과 같이 정의된다.type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
lib.es5.d.ts
금형의 제한을 가하는 토대에서 조건의else 한쪽은 : any
이다.: never
왠지...이
모드2: Union 배포
이것은 매우 어려운 이야기로 다음과 같은 유형에 부합된다.type Extract<T, U> = T extends U ? T : never;
언뜻 보니 나는 뜻이 분명하지 않다고 느꼈다.
이게 뭐하는 유형이냐면 유니온형을 전달하고 왼쪽 원소부터 오른쪽 원소까지 포함된 것만 남기는 유형이다.type Foo = Extract<"a" | "b" | "c" , "a" | "c" | "e">;
let x: Foo; // "a" | "c"
이게 왜 이렇게 움직였는지유형 스크립트 유형 기본에 대한 자세한 설명이 있어서 양보하고 싶어요.
점 생성 유니온 disitribution의 결과는 조건이 충족되지 않는 경우에만 never
유니온형에서 삭제됩니다.이를 위해 사용never
.
총결산
상기에서 말한 바와 같이 조건형 중 한쪽이 never
되는 경우는 조건분지 자체가 목적이라기보다는 부대적인 기능(infer와 uniondistribution)을 이용하는 경우가 많다.
그래서 이해하기 어려울 것 같지만 패턴을 이해하면'그렇군요. 이런 일을 하고 싶으세요?'
참고문
// union 型 Piyo を定義している感覚になるが、
// TypeScript においては Hoge | Fuga で既に型として成立しており
// Piyo はその別名をつけているに過ぎない
type Piyo = Hoge | Fuga;
// { bar: string } と直接書くことができるが、
// 何度も書くのは煩わしいし意図も伝えづらくなるため
// インターフェースに名前を与えて使いまわすことができる
interface Foo {
bar: string
}
infer
를 사용하여 몰드를 체크 아웃할 때 항상 실제 조건(또는 항상 실제 조건)을 사용하는 경우가 있습니다.이것은 흔히 볼 수 있는 모델이다.예를 들다.
// 型パラメータに与えた関数型の戻り値の型を取り出す型 ReturnType<T> を定義。
// ReturnType<(s: string) => number> とすると number になる。
// 既に定義されている関数を元にその戻り値の型を表したいときに使う(そのまんまの説明ですが…)
type ReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer R ? R : never;
뭐가 엉망진창이지만 매개 변수 부분을 숨겨서 읽으면 이렇게 돼요.type ReturnType<T extends (■■) => any>
= T extends (■■) => infer R ? R : never;
형 구속조건은 T extends (■■) => any
이므로 "T
은 함수형", T extends (■■) => infer R ? R : never
은T
이 함수형이면 반환값의 형을 R
R
으로 하고 그렇지 않으면 never
(불가능)으로 합니다.재형제약 때
extends (■■) => any
,'되지 않을 때'는'불가능'이기 때문에 실질? R
만 사용하기 때문에: never
.그럼 왜 조건을 붙여요?이것은
infer R
에서 반환 값 부분의 유형을 형 변수로 꺼내려고 하기 때문이다.이처럼'형 변수 중
infer
추출형의 일부분'을 위해 조건형을 사용하는 경우가 빈번하다.또 아까의 예는 처음부터
T
에게만 함수형을 전달하려고 했다.유형 제약을 더하면 전달 함수형 이외의 경우 컴파일 오류가 발생할 수 있지만 유형 제약이 없더라도 이 경우'조건 불충족'never
으로 인해 사용할 수 없기 때문에 유형 제약이 없어도 실용적일 수 있다.type ReturnType<T> = T extends (...args: any) => infer R ? R : never;
앞의 예는'항상 조건이 성립된 상황'이고 뒤의 예는'조건이 성립된 상황만이 구상할 수 있는 상황'이다.또한 실제
ReturnType<T>
는 표준 라이브러리에서 정의된 것으로 다음과 같이 정의된다.type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
lib.es5.d.ts 금형의 제한을 가하는 토대에서 조건의else 한쪽은
: any
이다.: never
왠지...이 모드2: Union 배포
이것은 매우 어려운 이야기로 다음과 같은 유형에 부합된다.type Extract<T, U> = T extends U ? T : never;
언뜻 보니 나는 뜻이 분명하지 않다고 느꼈다.
이게 뭐하는 유형이냐면 유니온형을 전달하고 왼쪽 원소부터 오른쪽 원소까지 포함된 것만 남기는 유형이다.type Foo = Extract<"a" | "b" | "c" , "a" | "c" | "e">;
let x: Foo; // "a" | "c"
이게 왜 이렇게 움직였는지유형 스크립트 유형 기본에 대한 자세한 설명이 있어서 양보하고 싶어요.
점 생성 유니온 disitribution의 결과는 조건이 충족되지 않는 경우에만 never
유니온형에서 삭제됩니다.이를 위해 사용never
.
총결산
상기에서 말한 바와 같이 조건형 중 한쪽이 never
되는 경우는 조건분지 자체가 목적이라기보다는 부대적인 기능(infer와 uniondistribution)을 이용하는 경우가 많다.
그래서 이해하기 어려울 것 같지만 패턴을 이해하면'그렇군요. 이런 일을 하고 싶으세요?'
참고문
type Extract<T, U> = T extends U ? T : never;
type Foo = Extract<"a" | "b" | "c" , "a" | "c" | "e">;
let x: Foo; // "a" | "c"
상기에서 말한 바와 같이 조건형 중 한쪽이
never
되는 경우는 조건분지 자체가 목적이라기보다는 부대적인 기능(infer와 uniondistribution)을 이용하는 경우가 많다.그래서 이해하기 어려울 것 같지만 패턴을 이해하면'그렇군요. 이런 일을 하고 싶으세요?'
참고문
매개변수 끝의 정의는
: never
인 것 같습니다...↩Reference
이 문제에 관하여(TypeScript 유형 정의의 ○○?△△: 네버가 뭐예요?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/chocolamint/items/2a551b0e3da9bad073a3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)