타입스크립트 교과서 3.1~3.4 정리

이수빈·2023년 9월 27일
0

Typescript

목록 보기
6/17
post-thumbnail

lib.es5.d.ts

  • ts에서 기본적으로 제공하는 타입선언이 모여있는 파일임.

  • 확장자가 d.ts인 이유? => 실제로 실행되는 코드는 없고 자바스크립트의 ㅌ아ㅣㅂ 선언만 들어가있음.(실제 구현은 JS에서 함)

  • 배열은 모든 파일에 인터페이스로 선언되어 있어 자동적으로 병합됨.

기본 Utility Type

partial

  • 기존의 객체 속성을 모두 optional 로 만드는 utility type
{
type Result = Partial<{a:string, b:string}>

type MyPartial<T> ={
    [P in keyof T]? : T[P];
}

type Result2 = MyPartial<{a:string, b:string}>

}

Required, Readonly

  • 모든 속성을 optional이 아니게 만들어줌

  • 앞에 readonly 키워드를 사용하면 모든 속성을 readonly로 만들어줌

  • -readonly로 적으면 => 모든 속성을 readonly 가 아니가 만들어줌

type MyRequired<T> = {
  (readonly)  [P in keyof T]-? : T[P];
} // -는 반대라는 의미

type Result3 = MyRequired<{a?:string, b?:string}>

as const vs readonly?

  • 객체를 as const로 정의를 해주게 되면 객체내의 모든 타입 속성들이 readonly로 바뀌는 것을 확인할 수 있다.

  • 만약 일부의 타입 속성들만 상수로써 바뀌지 않게 하고 싶다면 해당 타입 속성의 변수명의 앞에 readonly를 붙여주도록 한다.

  • 객체 자체를 상수처럼 쓰려면 as const, 속성 일부를 읽기전용으로 만드려면 readonly

const numbers1 = [1, 2]; // number[]
const numbers2 = [1, 2] as const; // readonly [1,2]

const plus = (a: number, b: number) => {
	return a + b;
}

console.log(plus(...numbers1)); // error
console.log(plus(...numbers2)); // fine
  • class에 field들을 고정하고 싶을때 readonly 키워드를 사용함.
class A {
  obj1 = { property: 123 } as const;
  // A.obj1: { readonly propery: 123 };
  readonly obj2 = { property: 123 };
  // A.obj2: { propery: number };
  readonly obj3 = { property: 123 } as const;
  // A.obj3: { readonly propery: 123 };

  setObj() {
    this.obj1 = { property: 123 }; // fine
    this.obj2 = { property: 123 }; // error
    this.obj3 = { property: 123 }; // error
  }

  setObjPropery() {
    this.obj1.property = 123; // error
    this.obj2.property = 123; // fine
    this.obj3.property = 123; // error
  }
}

Pick

  • 객체에서 지정한 속성만 가져오는 utility types

  • 지정한 속성을 포함한 객체 type을 반환함

  • T는 key중의 하나여아하므로, extends로 제약조건을 걸었음. => key값이 아닌게 들어오면 error발생

  • 속성에서 P값을 직접 extends하는 방법으로 이를 해결가능

    type Result = Pick<{a:string, b:string},'a'>
    
        type MyPick<T, K extends keyof T> = {
        [P in K] : T[P];
    }

        type Result2 = MyPick<{a:string, b:string, c:number},'a'|'c'|'d'> //error : d는 프로퍼티가아님

       

        type MyPick2<T, K> = {
        [P in K extends keyof T] : T[P];
    }
   

    type Result3 = MyPick2<{a:string, b:string, c:number},'a'|'c'|'d'>
//프로퍼티가 아닌값도 알아서걸러줌.

Record

  • 모든 속성의 타입이 동일한 객체의 타입
  • 동일한 type의 객체를 선언할 때 사용함
// <K, T> 형태로 선언해서 사용함.
    type Result4 = Record<"a"|"b", string>

컨디셔널 타입을 사용하는 Utility Type

  • 컨디셔널 타입일 때 유니언인 기존 타입과 제네릭이 만나면 분배법칙이 실행됨.

Exclude Type

  • 어떤 타입에서 지정한 타입을 제거함.

  • 1|"2"|3 은 union type이므로 분배법칙이 실행됨. => 그래서 result가 number만 남게 되는 형태임.

    type Result = Exclude<1|"2"|3, string>;

Extract Type

  • 어떤 타입에서 지정한 타입만 추출 => 객체에는 사용 불가능함.
    type Result3 = Omit<A, "a"|"c">

    type Result2 = Extract<A, string> //객체 type에는 사용 불가능함. never

Omit Type

  • Pick Type과 반대 => 특정 객체에서 지저안 속성 제거함.

  • 유니언을 만나면 분배법칙이 실행됨.

    type Result3 = Omit<A, "a"|"c">

NonNullable

  • 타입에서 null과 undefined를 제거

  • 객체에서 null, undefined를 제거하면 => keyof 연산자 + 인덱스 시그니처를 활용하면 됨.

type Result4 = NonNullable<string|null|number|undefined>

  type MyObject = {
  name: string | null;
  age: number | undefined;
  city: string;
};

type CleanedObject = {
  [K in keyof MyObject]: NonNullable<MyObject[K]>;
};

Optional

  • 일부 속성만 optional로 만드는 type(공식 utility type아님)

  • 먼저 Pick으로 객체에서 지정된 속성만 가져온뒤 이를 Partial로 만듬(일부 optional)

  • 다음 omit으로 지정된 속성을 제외한 type을 가져옴

  • 이 둘을 intersection함.

  type Optional<T, K extends keyof T> = Omit <T,K> & Partial<Pick<T,K>>

    type Result1 = Optional<{a:'hi', b:123}, 'a'>;

    //

const obj : Result1 ={
    b:123
}

infer를 사용하는 type

  • 함수에서 파라미터, return

  • 생성자함수에서 파라미터, 인스턴스 type 뽑아냄

  • abstract new 키워드를 사용한 이유 => 추상클래스까지 포함하려고 사용함.

    type Parameters<T extends (...args:any) => any> = T extends (...args : infer P) => any ? P : never; 

    type MyConstructorParameters<T extends abstract new (...args:any) => any> = T extends abstract new (...args : infer P) => any ? P : never; 


    type ReturnType<T extends (...args:any) => any> = T extends (...args : any) => infer R? R : any; 

    type InstanceType<T extends abstract new (...args:any) => any> = T extends abstract new (...args : any) => infer P ? P : any; 

This Type

  • 메서드들에 this를 한번에 주입하는 type임

  • 이런식으로 모든 형태를 정의할 수도 있지만, 코드 중복이 발생함.

  • 이럴때 this를 명시적으로 binding해주는 type

 type Data = {
        money : number
    };

    type Methods= {
        addMoney(this : Data& Methods, amount : number) => void;
        useMoney(this : Data& Methods, amount : number) => void;
    }

    type Obj = {
        data : Data,
        method : Methods
    }
    const obj:Obj = {
        data: {
            money : 0,
        },
        method : {
            addMoney(amount:number){
                this.money += amount;
            },
            useMoney(amount:number){
                this.money += amount;
            },
        }
    }
    
    // 이렇게도 작성가능

    type Methods= {
        addMoney(amount : number) => void;
        useMoney(amount : number) => void;
    }

    type Obj = {
        data : Data,
        method : Methods & ThisType<Data & Methods>;
    }

ref) https://velog.io/@pudding/typescriptconst-as-const-readonly

profile
응애 나 애기 개발자

0개의 댓글