[ Typescript ] - 조건문으로 타입만들기 & infer

최문길·2023년 12월 25일
0

Typescript

목록 보기
23/23

타입스크립트에서 객체 같은 interface도 있고, 함수와 같은 타입파라미터인 Generic도 있는데, 조건문이 없을까보냐 했는데

타입스크립트에서도 삼항연산자와 같은 문법이 존재한다



조건부로 타입만들어보기


type A<T> = T

const a : A<string> = 'str'

이러면 A<string> 쓰면 string이 남는다.
( 타입변수에도 타입파라미터 넣기가 가능하다요 )



이걸 조건부로
" 타입파라미터 자리에 string 타입 집어 넣으면 string, 그게 아니면 전부 unknown을 "
if문을 써보자




타입 조건식은 주로 extends 키워드와 삼항연산자 를 이용한다고 하는데

" extends는 왼쪽이 오른쪽의 성질(조건)을 가지고(만족)하냐 " 라는 뜻으로 사용 할수 있기에 조건식 용도로 사용가능하다고 한다.

수학에서 사용하는 ⊂ 역할인듯 함




type A<T> = T extends string ? string : unknown;
let a : A<string> // a는 string 타입
let b : A<number> // b는 unknown 타입

" T라는 파라미터가 string 성질을 가지고 있냐? 그러면 string 아니면 unknown "
이라는 말을 코드로 타자 치면 저렇게 쓴다.



조금더 나아가서

Q . type parameter로 array 자료를 입력하면 array의 첫 자료의 타입을 남겨주고 array 타입이 아니면 unknown 타입을 남겨주는 조건부 타입은?


type A<T> = T extends any[] ? T[0] : unknown

다른 예시로 ( extends가 최소한을 만족한다라는 말을 이해하기 위해서 )


type B = {
  length : number
}
type A<T> = T extends B ? T : any

let a :A<string[]> = ['asdf']; // a의 타입은 string[]
let b :A<number> = 1; //  b의 타입은 any




infer keyword



조건문에서 사용할 수 있는 특별한 infer 키워드가 있다.
infer 키워드는 지금 입력한 타입을 변수로 만들어주는 키워드라고 하는데..
글 만 읽어보면 먼 말인지 모르니 예시를 보자



type Person<T> = T extends infer R ? R : unknown;
type NewType =  Person<string> // NewTpye의 타입은 string 

infer 키워드의 특징은

  1. 조건문안에서만 infer 키워드를 사용할 수 있다.

  2. infer 우측에 자유롭게 작명해주면 타입을 T에서 유추해서 R 이라는 변수에 집어넣어주쇼 라는 의미
    그래서 위의 예제에서 <string> 이렇게 타입파라미터자리에 string 집어넣으면 R은 string이 된다.

  3. R을 조건식 안에서 맘대로 사용이 가능하다.


이런식으로 타입파라미터에서 타입을 추출해서 쓰고 싶을 때 쓰는 키워드라 생각하면 편할듯하다.

어떻게 써먹을까?



Sample 1.

array 안에 있던 타입이 어떤 타입인지 뽑아서 변수로 만들 수 있다 .


type Abstract<T> = T extends (infer R) [] ? R : unknown;
type NewType = Abastract<boolean[]> // NewType은 boolean 타입

이런식으로 (infer R) [ ] 면 array가 가지고 있던 타입부분만 쏙 뽑아서 R 변수에 할당이 가능하다.

뭔가... 뽑기 같은데?



Sample 2.

함수의 return 타입이 어떤 타입인지 뽑아서 변수로 만들어 줄 수 있다 .


type Abstract<T> = T extends ( () => infer R ) ? R : unknown;
type NewType = Abstract < () => number > // NewType은 number 타입

타입 파라미터에 <함수> 를 집어넣어 return 타입을 쏙 뽑아서 R이라는 변수에 담는 코드
그냥 infer를 사용하면 타입 추출이라고 이해하면 되겠다 .

ReturnType<> 예약 타입을 사용하면 return 타입만 뽑아서 알려준다.


위의 예제 처럼 거창할 필요없고

type 리턴타입 = ReturnType<()=>void> // 리턴타입은 void 입니다.

이게 더 좋을듯 함







더 나아가서

타입파라미터로
1. array 타입 인데 튜플인 array임
2. array의 첫 타입이 string 이면 타입을 그대로 받고
3. array의 첫 자료가 string이 아니면 unknown을 남겨주려면?


let test1 : A<[string, number]> // string 타입
let test2 : A<[boolean,number]> // unknwon 타입
























정답은

type A<T> = T extends [string,...any] ? T[0] : unknown

0개의 댓글