개발 공부/웹개발

Typescript: Generics, Enum, Utility type

크롱이크 2022. 4. 17. 14:14

 

  • 목차
    • Generics
    • Enum
    • Utility Type

Generics

  • 다양한 타입의 객체들을 다루는 메서드나 클래스에 컴파일 시의 타입 체크를 해주는 기능
  • 객체의 타입 안정성을 높이고, 형변환의 번거로움이 줄어든다. 강력한 타입 체크 가능
  • 제네릭이란 타입을 마치 함수의 파라미터처럼 사용하는 것을 의미한다.
  • 즉, 선언 시점이 아니라 생성 시점에 타입을 명시하여 하나의 타입만이 아닌 다양한 타입을 사용할 수 있도록 하는 기법이다. 한번의 선언으로 다양한 타입에 '재사용'이 가능하다는 장점이 있다.

 

function identity(arg: number): number {
  return arg;
}
function identity(arg: string): string {
  return arg;
}
function identity(arg: any): any {
  return arg;
}
function identity(arg: boolean): boolean {
  return arg;
}

-----------------

function identity<T>(arg: <T>): <T> {
	return arg;
}

다양한 타입 변수

타입 매개변수를 이렇게 표기하는 것이 관례이다.

하지만, 원한다면 자신이 원하는 대로, 표기하여 사용해도 문제가 되지 않는다.

T - Type
E - Element
K - Key
V - Value
N - Number
R - Return
U - Union
S, U, V .. - 2nd, 3rd, 4th types

사용 방법

// x
function identity(arg: number): number {
  return arg;
}
// o 
function identity<Type>(arg: Type): Type {
  return arg;
}


identity<string>("hero")

타입 제한 extends

  • Generic에 extends 을 붙여서 특정 타입을 가진 타입으로만 가능하도록 제한
  • 예시는 'LocalStorageType'
  • ReturnType을 제한함
import { accountType } from './type';
import { memberType } from './type';
import { productType } from './type';
import { salesType } from './type';

type LocalStorageType =
  | accountType
  | memberType
  | productType
  | salesType;
  
export const LocalStorageKeys = {
  salesVariables: (id: string) => `sales-variables-${gymId}`,
  productVariables: (id: string) => `product-variables-${gymId}`,
  accountVariables: (id: string) => `account-variables-${gymId}`,
  memberVariables: (id: string) => `member-variables-${gymId}`,
};

// 여기서 타입 제한
export const setLocalVariables = <ReturnType extends LocalStorageType>(
  key: string,
  variables: ReturnType,
): void => {
  window.localStorage.setItem(key, JSON.stringify({ ...variables }));
};

export const getLocalVariables = <ReturnType extends LocalStorageType>(
  key: string,
): ReturnType => {
  return JSON.parse(window.localStorage.getItem(key) as string);
};

// .사용하는 페이지
const localVariables = useMemo(
    () =>
      (id &&
        getLocalVariables(
          LocalStorageKeys.memberVariables(id),
        )) ||
      {},
    [id],
  );

 


enum (열거형)

  • Eumeration type :서로 연관된 상수들의 집합을 의미
  • 이름이 있는 상수들의 집합을 정의할 수 있다.
  • TypeScript는 컴파일러가 내보낸 최종 코드에서 enum을 자바스크립트 객체로 변환한다.
  • 특징
    • 키/값 세트로 정렬된다.
    • IDE의 지원을 받을 수 있다. (자동완성, 오타검증, 텍스트 리팩토리 등)
    • TypeScript의 열거형은 일반적으로 주어진 값에 대해 결정된 수의 옵션을 나타내는 데 사용된다.
    • 문맥(Context)을 담을 수 있다.

숫자 열거형

  • 자동 증가 숫자가 적용
  • 열거형 타입의 첫 번째 원소에 값을 할당하지 않으면 자동으로 0 할당
  • 각 한쌍(키/값) 에 대해 숫자 값만 있는 숫자 열거형에서만 작동한다.
enum CardinalDirection {
  North = 1,
  East,
  South,
  West,
};

// 첫번째 값으로 숫자를 사용 -> 나머지 값에도 숫자를 할당

compile 결과

var CardinalDirection;
(function (CardinalDirection) {
    CardinalDirection[CardinalDirection["North"] = 1] = "North";
    CardinalDirection[CardinalDirection["East"] = 2] = "East";
    CardinalDirection[CardinalDirection["South"] = 3] = "South";
    CardinalDirection[CardinalDirection["West"] = 4] = "West";
})(CardinalDirection || (CardinalDirection = {}));
;

 

문자 열거형

TypeScript 컴파일러는 기본적으로 열거형 멤버에 숫자를 할당하지만 이를 재정의하여 문자열 열거형을 만들 수 있다.

 

enum CardinalDirection {
  North = 'N',
  East = 'E',
  South = 'S',
  West = 'W'
}

compile 결과

var CardinalDirection;
(function (CardinalDirection) {
    CardinalDirection["North"] = "N";
    CardinalDirection["East"] = "E";
    CardinalDirection["South"] = "S";
    CardinalDirection["West"] = "W";
})(CardinalDirection || (CardinalDirection = {}));

 

양방향 열거형

열거형의 각 멤버가 개체( CardinalDirection["North"] = 1])의 속성이 되는 것 외에도 열거형은 각 숫자에 대한 키를 만들고 문자열을 값으로 할당합니다. 의 경우 값 North을 CardinalDirection["North"] = 1반환 하고 키에 값을 1할당 CardinalDirection[1] = "North"합니다 .

enum CardinalDirection {
  North = 1,
  East,
  South,
  West,
};

// compile 결과

"use strict";
var CardinalDirection;
(function (CardinalDirection) {
    CardinalDirection[CardinalDirection["North"] = 1] = "North";
    CardinalDirection[CardinalDirection["East"] = 2] = "East";
    CardinalDirection[CardinalDirection["South"] = 3] = "South";
    CardinalDirection[CardinalDirection["West"] = 4] = "West";
})(CardinalDirection || (CardinalDirection = {}));

enum CardinalDirection {
  North = 'N',
  East = 'E',
  South = 'S',
  West = 'W',
};

const direction: CardinalDirection = CardinalDirection.North;

const direction: CardinalDirection = false;
// Type 'false' is not assignable to type 'CardinalDirection'. (2322)

 

퀴즈

- 자동 증가 숫자로 Tuesday 에도 2의 값이 들어가고 Thuesday에는 2의 값을 할당해 같은 값을 가지게 되었다.
에러가 발생할까?

enum DayOfWeek {
  Sunday = 0,
  Monday ,
  Tuesday,
  Wednesday = 10,
  Thursday = 2,
  Friday,
  Saturday
}

정답 확인

 

 

 

 

 

 

enum을 사용하지 않는 이유

• enum으로 타입이 지정된 변수에 다른 숫자를 할당할 수 있기 때문에 연관되지 않는 숫자도 할당할 수 있다.

(불확실성 증가)

 

반응형