Typescript D3

🐳ㅇㅡㄴㄱㅓ·2022년 10월 19일
0

사내스터디

목록 보기
2/7

유틸리티 타입

// Sample
type User = {
	name: string;
	age: string;
	gender?: string;
}

Partial<T>

  • T의 모든 프로퍼티를 옵션 프로퍼티로 지정하여 새 타입을 구성한다.
/**
type PartialUser = {
    name?: string | undefined;
    age?: string | undefined;
    gender?: string | undefined;
}
*/

type PartialUser = Partial<User>;

Required<T>

 * T에 옵션 프로퍼티가 있어도 Required<T> 로 선언시에는 모든 프로퍼티가 필수값으로 지정하여 새 타입이 구성된다.

/*
type RequiredUser = {  
name: string;  
age: string;  
gender: string;  
}
*/
type RequiredUser = Required<User>;

Pick <T, K>

  • T에서 K 만 "Pick" 해서 새로운 타입을 구성
  • 예를들어 밑의 예쩨에서pick 하지 않은 다른 Book type 속성을 Book Preview type에서 사용하면 오류가 발생한다. - BookPreview 타입은 name과 image로만 구성된 타입이기 때문에
type Book = {
    name: string,
    ISPN: number,
    price: number,
    image: string,
    description: string
}

/**
type BookPreview = {  
	name: string;  
	image: string;  
}
*/
type BookPreview = Pick<Book, "name" | "image">;

Omit <T, K>

  • T에서 K 프로퍼티를 제거한 후 새 타입을 구성
  • PricelessItemT로 사용하면 price, currency는 없는 프로퍼티라서 사용을 할 수가 없음.
type Item = {
    name: string;
    description: string;
    price: number;
    currency: string;
}

/**
type PricelessItem = {  
	name: string;  
	description: string;  
}
*/
type PricelessItem = Omit<Item, "price" | "currency">;

Readonly <T>

  • T의 모든 속성을 읽기 전용으로 설정한 타입 구성
/**
 * const 로 선언된 값은 바꿀 수 없지만 array나 object로 값이 들어가있으면 그 안의 필드는 쉽게 업데이트 가능
 * as const를 추가해주면 업데이트 할 수 없이 불변값이 됨.
 */

const user3 = {
    name: "elin",
    age: 34
} as const;

//읽기 전용 속성이므로 'name'에 할당할 수 없습니다.
user3.name = "elin K";
console.log(user3);
/**
 * 여기서 readonly 속성은 첫번째 레벨까지만 적용되는 속성이기 때문에 degree의 변경까지는 막을 수 없음.
 * degree 속성 앞에까지 readonly 를 추가해야 업데이트를 막을 수 있음.
 * 배열에도 readonly 추가를 하면 값 변경은 막을 수 없지만 push 까지는 막을 수 없고
 * 이 경우에 Readonly<T>나 ReadonlyArray<T> 로 타입지정을 해주면 push 할 때도 에러가 뜨는 것 확인 가능
 */

type User2 = {
    readonly name: string;
    readonly age: number;
    readonly education: {
        readonly degree: string;
    };

    readonly skills : ReadonlyArray<string[]>
}

const user4: User2 = {
    name : "John Doe",
    age: 26,
    education: {
        degree : "SE"
    },
    skills : ["Javascript", "Typescript"]
};
//읽기 전용 속성이므로 'name'에 할당할 수 없습니다.
user4.name = "Jane Doe";
// 읽기 전용 속성이므로 'age'에 할당할 수 없습니다.
user4.age = 22;
//읽기 전용 속성이므로 'degree'에 할당할 수 없습니다.
user4.education.degree = "SEE";
//읽기 전용 속성이므로 'skills'에 할당할 수 없습니다.
user4.skills = ["AWS"];
//'readonly string[][]' 형식에 'push' 속성이 없습니다.
user4.skills.push("Developer");

Record <K, T>

  • 타입 T의 프로퍼티 집합 K로 타입을 구성
  • number의 프로퍼티 집합 string 으로 타입을 구성....?
    => 쉬운말버전 : 프로퍼티의 키값을 K 타입으로, 값을 T 타입으로 하는 타입을 구성할 수 있다.
  • Union Type 과 조합해서 키값이 제한된 타입을 만드는 것도 가능
/*
type AgesType = {
    [name: string]: number;
};
*/

type NamesType = 'John Doe' | 'Jane Doe' | 'Baby Doe';
type AgesType = Record<NamesType, number>;

const ages: AgesType = {
    'John Doe' : 29,
    'Jane Doe' : 25,
    'Baby Doe' : 5
};

그 외 타입들

  • Exclude<T, U> / Extract<T, U>
/*
* Exclude<T, U>
*  - T 타입들 중 U타입들과 겹치는 타입을 제외
 *
 * Extract<T, U>
 * - Exclude랑은 다르게 겹치는 것만 가져옴
 */

type Phone = "Samsung" | "Apple" | "LG";
type Notebook = "LG";

// type Sample = "Samsung" | "Apple"
type Sample = Exclude<Phone, Notebook>;     //겹치는거 빼고 가져옴
// type Sample2 = "LG"
type Sample2 = Extract<Phone, Notebook>;    //겹치는 것만 가져옴
  • NonNullable<T>
//T 타입에서 null or undefined 제외하고 리턴
//string | number
type Sample3 = NonNullable< string | number | undefined >;
  • Parameters<T>
/**
 * Parameters<T>
 * - 함수의 파라미터에 사용된 타입을 튜플 타입으로 생성
 * - 함수타입이 아닌 것을 T 자리에 넣으면 에러 발생하고 never 타입이 반환된다.
 * - any -> unknown[] 나오고 never -> never 나옴
 */

type Sample4 = Parameters<typeof handler2>;
type Sample5 = Parameters<any>;
type Sample5 = Parameters<string>;
type Sample6 = Parameters<(a: string) => number>;
  • ConstructorParameters<T>
/**
 * ConstructorParameters<T>
 * - Parameters와 비슷하지만 T로 들어갈 수 있는 값이 생성자 파라미터로 한정된다 Class 들어가야된다는 소리
 */

// type S7 = [name: string, age: number]
type S7 = ConstructorParameters<typeof Person>;
  • ReturnType<T>
/**
 * ReturnType<T>
 * - T라는 함수의 리턴타입을 가져옴
 * - T자리에 함수타입이 아니면 오류남.
 */
function handler(eventType: `on${string}`) {
    console.log(`handling ${eventType}`);
}

//type S8 = void handler 함수가 리턴없이 log만 찍고있기 때문에 void로 타입이 지정됨.
type S8 = ReturnType<typeof handler>;
  • InstanceType<T>
/*
 * InstanceType<T>
 * - T라는 생성자 함수의 인스턴스 타입을 반환
 */

class Student extends User {
    grade: number;
}

// type S9 = Student
type S9 = InstanceType<typeof Student>;
  • ThisParameterType<T>
/**
 * ThisParameterType<T>
 * - T라는 함수타입에서 this 파라미터의 타입을 반환. 반환될 값이 없는 함수라면 unknown 반환
 */

function toUpper(this: string) {
    return this.length;
}

//type S10 = string
type S10 = ThisParameterType<typeof toUpper>;
  • OmitThisParameter<T>
/**
 * OmitThisParameter<T>
 * - T 함수에서 this 파라미터만 제거한 타입을 생성한다.
 * - 테스트해보면 this 파라미터는 빠져있고 리턴되는 number 타입만 나옴
 */

//type S11 = () => number
type S11 = OmitThisParameter<typeof toUpper>;

번외 - 기타 Tip

Non-Null Assertion operator

type Movie = {
    title : string,
    grade : number,
    time? : string
}

const movie:Movie = {
    title: "spicer man",
    grade: 4.5,
    time: "400"
};

/**
 * movie type에서 time 속성이 옵션 속성을 가지고 있어서 string 이거나 undefined 상태일수도 있으므로 오류가 발생한다
 * 이 경우 뒤에 느낌표를 붙여주면 null이나 undefined 값 오류가 없어짐.
 * 느낌표를 붙임으로써 이 값이 null이나 undefined가 아니라고 단언하는 타입 단언의 한 종류
*/

const movieTime: string = movie.time!;

console.log(movie);

typeof XXX

  • 이미 주어진 데이터를 가지고 Type을 구성한다.
const arr = [1, 2, 3];

/**
* 
type Video = {  
	title: string;  
	grade: number;  
	time?: string | undefined;  
}
*/
type Video = typeof Movie;

Template Literal

  • 템플릿 리터럴과 Type 을 조합해서 Type 범위를 제한할 수 있음
function handler(eventType: `on${string}`) {
    console.log(`handling ${eventType}`);
}

function handler2(eventType: `on${'Click' | 'Keydown'}`) {
    console.log(`handling ${eventType}`);
}

handler('onClick');
handler('onKeydown');
handler('escape');      //handler 함수 파라미터 타입에서 on 으로 시작하는 스트링타입을 지정해두었기 때문에 오류

handler2('onClick');
handler2('onKeyup');    //handler2 함수에서는 onClick, onKeydown에 대해서만 type을 허용했기 때문에 에러

class constructor에서의 public

  • 생성자 선언 시 파라미터 앞에 public을 붙여주면 별도의 속성선언 없이 바로 access 가능
class Person {
    constructor(public name: string, private age: number) {

    }
}

const johnDoe = new Person("John Doe", 34);
//Person {name: 'John Doe', age: 34}
console.log(johnDoe);

회고

  • egghead 강의를 영어라서 살짝 외면했는데 생각외로 짧고 심플하게 유틸리티타입을 익힐 수 있는 과정이었다
  • 근데 저걸 뭐를 제일 많이 쓰고 어떤상황에서 딱 써야할지는 아직 감이 안오고 실제 api 만들면서 확인해봐야될것같다
  • 근데 DB연결부터 안 되서 뭘 해볼 수 없어 빡치는중

참고

TypeScript: Tips and Tricks | egghead.io
[Typescript] 유틸리티 타입 - 1
Typescript 유틸리티 클래스 파헤치기. Utility Types Docs를 중점으로 | by Harry The Great | 해리의 유목코딩 | Medium
GitHub - piotrwitek/utility-types: Collection of utility types, complementing TypeScript built-in mapped types and aliases (think "lodash" for static types).

profile
재활훈련 중

0개의 댓글