개발일지

[TS] 10. 타입스크립트의핵심 #2 - index, mapped, conditional type 본문

JS, TS/[TS | 강의] TS·OOP

[TS] 10. 타입스크립트의핵심 #2 - index, mapped, conditional type

lyjin 2022. 11. 9.

Index Signatures:

  • JS(TS)에서 Object에 들어있는 다른 객체를 참조할 때 문자열로 접근할 수 있다.
const obj = {
  name: 'ellie',
};
obj.name; // ellie
obj['name']; // ellie

 

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

// 예시1.
type Name = Animal['name']; // string
const text: Name = 'hello';
const text2: Name = 1; // error

// 예시2.
type Gender = Animal['gender']; // 'male' | 'female'

// 예시3.
type Keys = keyof Animal; // 'name' | 'age' | 'gender'
const key: Keys = 'gender';

// 예시4.
type Person = {
  name: string;
  gender: Animal['gender']; // 'male' | 'female'
};
const person: Person = {
  name: 'ellie',
  gender: 'male',
};

 

keyof

  • Object의 key의 리터럴 값들을 가져온다.
type Keys = keyof Animal; // 'name' | 'age' | 'gender'
const key: Keys = 'gender';

 


Mapped type:

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

type VideoOptional = {
  title?: string;
  author?: string;
};

type VideoReadOnly = {
  readonly title: string;
  readonly author: string;
};
  • 만약 새로운 필드를 추가하고 싶다면? 모두 readonly로 만들고 싶다면? 모두 number type으로 변경하고 싶다면? > 정의된 type 요소 하나하나 다 수정해줘야하기때문에 번거롭다.
  • 이를 간편하고 재사용성을 높여주는 것이 mapped type

 

Mapped type

 

// [1, 2].map(item => item * item); // [1, 4]

type Heroes = 'Hulk' | 'Thor' | 'Capt';

// 각각 나이를 추가하고 싶다면?
type HeroProfiles = { [K in Heroes]: number };
const heroInfo: HeroProfiles = {
  Hulk: 54,
  Thor: 1000,
  Capt: 33,
}
  • [K in Heroes] : js의 for in 문법과 유사하게 동작. Heroe의 문자을 순회하며 number 타입의 값을 가지는 객체의 키로 정의됨

 

// 예시1. Optional
type Optional<T> = {
  [P in keyof T]?: T[P]; // for...in 역할
};
type VideoOptional = Optional<Video>;

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

const animal: Optional<Animal> = {
  name: 'dog',
};
animal.name = 'ellie';

 

// 예시2. ReadOnly
type ReadOnly<T> = {
  readonly [P in keyof T]: T[P];
};

const video: ReadOnly<Video> = {
  title: 'hi',
  author: 'ellie',
};

video.title = 'hello'; //error

 

// 예시3. Nullable
type Nullable<T> = { [P in keyof T]: T[P] | null };

const obj2: Nullable<Video> = {
  title: 'hi',
  author: null,
};

 

// Typescript Proxy 예시
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
  • T가 string에 할당될 수 있으면 boolean 타입, 아니면 number 타입이 된다.

// Typescript TypeName 예시
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<'a'>;        // 'string'
type T2 = TypeName<() => void>; // 'function'