본문 바로가기
  • 살짝 구운 김 유나
Web/TypeScript

[TypeScript] Utility Type

by yunae 2023. 3. 5.

타입스크립트에서는 타입을 변환하는 것이 가능하다.

- 한 타입의 일부분을 새로운 타입으로 이용 가능

- 한 타입을 기본으로 하여 다른 타입으로 이용 가능

 

 

Index Type

: 특정 타입의 Index에 기반한 타입

객체의 value는 다음과 같이 접근 가능하다.

const obj = {
    name: "yuna",
};

obj.name; // yuna
obj["name"]; // yuna

Animal이라는 타입을 선언한 뒤, 타입의 인덱스에 기반한 타입을 새로운 타입으로 사용할 수 있다.

type Animal = {
    name: string;
    age: number;
    gender: "male" | "female";
};

type Name = Animal["name"]; //string
const text: Name = "rabbit";

type Gender = Animal["gender"]; // 'male' | 'female'

// 각 키를 타입으로 지정할 수 도 있다.
type Keys = keyof Animal; // 'name' | 'age' | 'gender'
const key : Keys = 'gender'

// 객체 타입을 선언할 때도 사용 가능하다.
type Person = {
    name: string;
    gender : Animal['gender']
}

const person = {
    name : 'yuna',
    gender: 'female', // 'male' | 'female' 중 하나의 값만 가능하다.
}

 

 

Mapped Type

: 기존의 타입들을 이용하면서 조금 다른 형태로 변환한 타입

다음과 같이 비효율적인 타입들이 있다..

type Video = {
    title: string;
    author:string;
}

// 선택 입력 video
type VideoOptional = {
    title?: string;
    author?: string;
    description?: string;
}

// 읽기 전용 video
type VideoReadOnly = {
    readonly title: string;
    readonly author: string;
    readonly description: string;
}

 

map type 적용

 

type 타입명<T> = {
    [P in keyof T]: T[P] // for .. in과 동일, object key를 하나씩 돌아
}

위의 코드를 아래와 같이 개선할 수 있다.

=> Video 타입의 재사용성을 높임

type Video = {
    title: string;
    author:string;
}

type Optional<T> = {
    [P in keyof T]?: T[P] // for .. in과 동일, object key를 하나씩 돌아
}

type ReadOnly<T> = {
    readonly [P in keyof T]: T[P]
}

// Video 타입의 key를 빙글빙글 돌면서 물음표 붙여주기
type VideoOptional = Optional<Video>
// Video 타입의 key를 빙글빙글 돌면서 readonly 붙여주기
type VideoReadOnly = Optional<Video>

선언 하면서 동시에 사용하는 것도 가능하다.

type Animal = {
    name: string;
    age: number;
};

const animal: Optional<Animal> = {
	// Animal type의 모든 프로퍼티를 가질 필요는 없음 
	name: "kitten",
};
type Proxy<T> = {
    get(): T;
    set(value: T): void;
  };

  type Proxify<T> = {
    [P in keyof T]: Proxy<T[P]>;
  };

 

 

Conditional Type

: 조건적으로 타입을 결정하는 타입

type Check<T> = T extends string ? boolean : number;
type Type = Check<string>; //boolean

삼항연산자로 표현한다.

type typeName<T> = T extends string
    ? "string"
    : T extends number
    ? "number"
    : T extends boolean
    ? "boolean"
    : T extends undefined
    ? 'undefined'
    : T extends Function
    ? "function"
    : "object";

type T0 = typeName<string>; // string
type T1 = typeName<"str">; // string
type T2 = typeName<() => void>; // function

 

 

앞에서 살펴본 타입들은,

기존의 타입을 보장하고 유지하고 재사용하면서 다른 종류의 타입으로 변환한다!

 

사실 우리가 만들고 싶은 대부분의 타입은 이미 만들어져 있다. => Utility Type

 

 

ReadOnly

다음과 같은 상황이 발생했다고 하자.

type ToDo = {
    title: string;
    description : string;
}

// title을 보여주기만 하고 싶은데 변경해버리는,,,,그런,,상황
function display(todo: ToDo) {
    todo.title = '타이틀 변경해버려,,,'
}

Readonly Type 사용하기

type ToDo = {
    title: string;
    description : string;
}

function display(todo: Readonly<ToDo>) {
    todo.title = '타이틀 변경해버려,,,'
}

 

Readonly 타입을 command(Mac)를 누른채로 클릭하면 타입의 정의가 어떻게 되어있는지 볼 수 있다.

 

 

Partial Type

: 기존의 타입 중에서 부분적인 것만 허용하고 싶을 때

ex) 객체의 일부분 수정

type ToDo = {
    title: string;
    description: string;
    label: string;
    priority: "high" | "low";
};

function updateTodo(todo: ToDo, fieldsToUpdate: Partial<ToDo>): ToDo {
	return { ...todo, ...fieldsToUpdate };
}

const todo: ToDo = {
    title: "learn TypeScript",
    description: "Study Hard",
    label: "Study",
    priority: "high",
};

const updated = updateTodo(todo, { priority: "low" });

console.log(updated)

 

 

Pick Type

: 기존의 타입에서 원하는 속성, 값만 골라서 하나의 타입으로서 사용하는 것

type Video = {
    id: string;
    title: string;
    url: string;
    data: string;
  };

  function getVideo(id: string): Video {
    return {
      id,
      title: "video",
      url: "https://..",
      data: "byte-data..",
    };
  }

id, title만 가져오는 함수를 만들고 싶다면? => Pick Type을 사용한다.

// 재사용성을 위해 주로 따로 선언하여 사용한다.
type VideoMetaData = Pick<Video, 'id' | 'title'>

function getVideoMetaData(id: string): VideoMetaData {
    return {
        id,
        title: 'title',
    }
}

 

 

Omit Type

: Pick과 반대로 특정 타입에서 원하는 속성과 값을 뺀 새로운 타입을 만들 수 있음

type Video = {
  id: string;
  title: string;
  url: string;
  data: string;
};

// url과 data 키를 제외한 타입
type VideoMetaData = Omit<Video, 'url' | 'data'>

function getVideoMetaData(id: string): VideoMetaData {
  return {
      id,
      title: 'title',
  }
}

 

 

Record Type

: 두 가지 타입을 서로 엮을 수 있는 타입

ex) Page를 key로 PageInfo를 value로 엮어보기

type PageInfo = {
  title: string;
};

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = {
  home: { title: "Home" },
  about: { title: "About" },
  contact: { title: "Contact" },
};

 

'Web > TypeScript' 카테고리의 다른 글

[TypeScript] 타입스크립트 컴파일러  (0) 2023.03.07
[TypeScript] 제네릭 (Generics)  (0) 2023.03.01
[TypeScript] Composition  (0) 2023.02.25
[TypeScript] 객체지향 (OOP)  (0) 2023.02.24
[TypeScript] 기본 타입 #2  (0) 2023.02.22

댓글