티스토리 뷰
위 그림에서 never는 아주 작은 점, unknown은 전체를 포함하고 있다는것을 잘 기억하자.
unknown
다른 모든 타입들의 슈퍼셋이다.
모든 타입들은 unknown타입이다.
never
다른 모든 타입들의 서브셋이다. 가장 최하위 개념의 타입이다.
따라서, 그 어떤 다른 타입들도 never타입일 수 없다.
never는 never그 자체다.
T | never ⇒ T
never는 그 어떤 타입도 아니기 때문에 union을 하더라도 그대로다.
T & unknown ⇒ T
unknown은 모든 타입들의 superset이기 때문에 unknown과 어떤 타입 T를 교집합하면 그대로 T가 나온다.
never로 타입 추론 예외를 제거하자.
type Arguments<T> = T extends (...args: infer A) => any ? A : never
T가 함수인경우에만 그 함수에 전달된 argument들의 타입을 추론하는 type alias를 만들었다.
여기서 infer A는 뭘까? (링크)
interface Example {
foo: string
}
type GenericExample<T> = T extends Examlep ? 'foo' : 'bar';
만약에 이런 interface와 type alias가 있다고 해보자.
이때 개발자가 오타로 Examlep이라고 적었음에도 불구하고 GenericExample<'helloworld'>가 정상적으로 'foo'라는 타입으로 추론된다. T에 어떤 타입이 들어오든 무조건 'foo'로 추론된다. 이렇게 개발자의 실수를 방지하지 못하게 된다.
왜냐면 타입스크립트는 Examlep이라는 오타가 오타인건지 실제 존재하는 타입인지 확인하지 않기 때문이다.
interface Example {
foo: string
}
type GenericExample<T> = T extends infer Examlep ? 'foo' : 'bar';
이런식으로 infer를 통해 명시적으로 타입을 추론하면 타입스크립트가 Examlep이라는 타입은 없는데? 라면서 컴파일 에러를 내뱉어준다.
이제 다시 본론으로 돌아가자.
type Arguments<T> = T extends (...args: infer A) => any ? A : never
만약에 T라고 하는 타입이 (...args: infer A) => any 형태의 함수라면?
Arguments type alias를 A의 타입으로 추론하고
만약에 함수가 아니라면 never타입으로 추론된다.
never타입에는 그 어떤 값도 할당할 수 없기 때문에 Arguments<T>의 T부분에 함수가 아닌 타입이 오게 되면 무조건 컴파일 에러가 발생한다. 이런식으로 never를 활용 할 수 있다.
type Return<T> = T extends (...args: any[]) => infer R ? R : never
이런 형태도 마찬가지다.
T가 함수라면 그 함수의 리턴값을 추론해서 Return type alias의 타입으로 정하고,
만약에 T가 함수가 아니라면 never로 추론하게 해서 에러를 내뱉게 만든것이다.
type NonNullable<T> = T extends null | undefined ? never : T;
이 헬퍼타입은 타입스크립트에서 제공하는 유틸성 타입이다. 어떤 union 타입에서 null이나 undefined를 제거해준다. 중요한것은 NonNullable의 T에 들어오는 타입은 반드시 null이나 undefined를 갖는 union 타입이어야 한다는것이다.
T에 null이나 undefined가 없으면 에러가 발생한다.
위 문장은 아래와 같이 변경된다.
// 만약에 T가 A | B 유니온 타입이라면
T extends null | undefined ? never : T;
// 아래와 같이 변경된다.
(A extends null | undefined ? never : A) | (B extends null | undefined ? never : B);
이게 무슨말인지 잘 모르겠다. 예시를 살펴보자.
NonNullable<string | null>
// T가 string | null 유니온 타입이라면
== (string extends null | undefined ? never : string) | (null extends null | undefined ? never : null)
// string은 null | undefined가 아니므로 string type
// null은 null | undefined이므로 never type
== string | never
// never와 string의 union은 string이다.
== string
그래서
NonNullable<string | null> == string
이 된다. (유니온 타입에서 null이 제거 되었다.)
결론
never는 잘못된 타입이 들어오는걸 방지하는 역할을 하게 만들 수 있다.
조건부 타입에서 infer 키워드의 역할은 infer 다음에 오는 타입이 진짜 존재하는 타입인지 확인해서 정확한 타입 추론이 이뤄지게 만들어준다.
'Typescript' 카테고리의 다른 글
typescript의 unknown과 any의 차이 (0) | 2020.07.16 |
---|---|
typescript의 never타입 (0) | 2020.07.16 |
스토리북 typescript bug, import된 타입을 불러오지 못하는 현상 (0) | 2020.05.29 |
fork-ts-checker-webpack-plugin 란 (0) | 2020.05.29 |
typescript + react eslint룰 설정 (0) | 2020.05.29 |
- Total
- Today
- Yesterday
- design system
- Polyfill
- server side rendering
- reducer
- return type
- react hooks
- props
- state
- Action
- await
- mobx
- computed
- es6
- Next.js
- promise
- atomic design
- useRef
- reactdom
- hydrate
- useEffect
- storybook
- async
- typescript
- Babel
- type alias
- reflow
- rendering scope
- react
- webpack
- javascript
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |