타입스크립트 교과서 2.22~2.32 정리

이수빈·2023년 9월 20일
0

Typescript

목록 보기
5/17
post-thumbnail

Infer를 통한 타입스크립트 추론

  • 컨디셔널 타입과 함께 사용, 추론하려는 부분을 infer로 만들면 됨

  • 파라미터도 모르는 상태니 제너릭으로, infer E라는 변수로 알아서 추론해서 배열의 원본타입을 얻도록 해줌.

  • 타입변수처럼 사용하게 해주는 기능임, Parameter, Return type등을 추론할 때 사용함.

type El<T> = T extends (infer E)[] ? E : never; //E가 타입변수 

type Test<T> = T extends any[] ? T : never;  //E가 타입변수 배열이 있을 때 배열의 요소타입을 얻냄


type Str = El<string[]> // string

type test2 = Test<string[]>; // string[] 타입..!! => 새로운 변수 도입해야함..
 
  • 예시 2

  • 함수 타입을 입력으로 받아서 반환타입을 추출하는 type임!! infer 키워드는 추론이 필요한 곳에서 선언할 것

type ReturnTypeOfFunction<T> = T extends (...args: any[]) => infer R ? R : never;

function greet(name: string): string {
  return `Hello, ${name}!`;
}

type GreetReturnType = ReturnTypeOfFunction<typeof greet>; // string
                                            
type MyParameters<T> = T extends (...args: infer P) => any ? P : never; // Parameter 뽑아내는 fn
  • infer로 타입변수를 여러개 사용가능함
type MyPAndR<T> = T extends (...args:infer P) => infer R ? [P,R] : never;

type PR = MyPAndR<(a:string, b:number) => string>;
  • 같은 이름의 타입변수를 여러곳에 사용 할 수 있음. 기본적으로 반환값일 때, 같은 이름의 타입변수는 union이 되지만, 매개변수일 경우 intersetion이 됨.

  • 동시에 2가지를 만족시켜야하므로 => union type

  • 하나의 매개변수를 넣었을 때 2가지를 모두 만족시켜야 하므로 => intersection type

type Union<T> = T extends {a: infer U, b: infer U} ? U : never;
type Result1 = Union<{a : 1|2 , b: 2|3}>

type intersection<T> = T extends {
    a : (pa : infer U) => void,
    b : (pb : infer U) => void  
} ? U : never;

type Result2 = intersection<{a: (pa: 1|2)=> void, b: (pb:1|3)=>void}

타입가드

  • typeof 연산자 이외에도 여러가지 사용가능.

  • undefined, null도 활용할 것. typeof null 은 object이므로 직접 거를때는 동등비교를 통해 null을 구분

  • 배열 => Array.isArray함수 사용가능, class => instanceof 연산자 활용가능.

  • in 연산자를 통해 속성이 있는지 확인여부로 구분 가능

  • type을 구분하는 브랜드속성 사용가능

  • 서술타입 존재

재귀타입

  • type안에서 자기자신을 참조하는 type임

  • 원시 타입의 경우 해당 원시 타입을, 배열의 경우 원소의 타입을 얻는 유틸 함수를 작성한다면 다음과 같이 작성해볼 수 있다. (배열의 인자 타입으로 number를 넣으면 원소의 타입을 얻을 수 있다. index의 타입이 number 이기 떄문에)

  • 타입인수로 사용하는 것은 불가능함.=>타입인수가 아닌 방향으로 수정


    type ElementType<T> = T extends any[] ? ElementType<T[number]> :T;

    type Result1 = ElementType<number[]>; //number

// T=string[], Result = string
// T=number[], Result = number

	 type T = number | string | Record<string,T> // refer itself 

    type T = number | string | {[key:string] : T}; // 타입인수를 쓰지 않으면 가능함.

템플릿리터럴 타입

  • 특수한 문자열 타입임. 값 대신 타입을 만들기 위해 사용함.

  • 타입의 조합에서 편의성이 존재함 아래와 같은 코드에서 type이 추가된다면, City와 Vehicle에 타입을 각각 넣어주면 됨

  • 이게 조합형태로 만들때 사용함 => 3x3 이런식으로

  • 템플릿리터럴 타입은 재귀호출이 가능함!

    type City = "seoul" |"suwon"|"busan";
    type Vehicle = "car" | "bike" | "walk";
    type Id = `${City}:${Vehicle}`; //3x3타입을 자동생성해줌

type RemoveX<Str> = Str extends `x${infer Rest}` ? RemoveX<Rest> : Str extends `${infer Rest}x` ? RemoveX<Rest> : Str; // 재귀호출타입

type Removed = RemoveX<"xxtestxx">

satisfies 연산자

  • 4.9버전에 추가됨. => 추가적인 타입검사를 하고싶을 때 사용함

Type assertion

  • 타입주장은 변수에 적용해야만 타입이 유지됨.

  • 조건절에서 error를 타입 assertion해도 조건절을 빠져나오면 TS는 이를 판단하지 못함. (조건절에서만 일시적으로 사용하기 때문.)

 try{}
    catch(error){
        if(error){
            error.message;
        } // error => unknown type, if문을 통과하면 {} 타입이됨.
    }
{
    try{}
    catch(error){
        if(error as Error){
            error.message;
        } // error => unknown type, if문을 통과하면 {} 타입이됨.
    }
}
  • 해결방법 => 바깥스코프에서 변수를 선언하거나, instanceof 연산자 활용

  try{}
    catch(error){
        const err = error as Error ;
        if(err){
            err.message;
        } // 변수활용코드
    }

    try{}
    catch(error){
        if(error instanceof Error){
            error.message;
        } // instanceof 연산자 활용
    }

데코레이터

  • 5.0부터 추가된 기능 => 함수를 래핑하는 기능임 (중복로직 적용가능함)
profile
응애 나 애기 개발자

0개의 댓글