Typescript 기본타입 (~enum타입까지)

늘보·2021년 7월 10일
1

Typescript

목록 보기
1/2

Typescript의 몇 가지 특징

정적언어. 안정성, 생산성이 높다.

TS가 JS로 변환되는 과정은?

const v1: number | string = 123;
const v2 = () => console.log('123');
// TS -> JS로 변환된 파일
"use strict";
var v1 = 123;
var v2 = function () { return console.log('123'); };
  • 위의 코드는 ts.config.json 파일의 compilerOptions에서 target프로퍼티의 value값을 es5로 설정 했을 때 저런 식으로 변환이 된다.

number, string, array, tuple 타입

const size: number = 123;
const isBig: boolean = size >= 100;
const msg: string = isBig ? '크다' : '작다';

// array 타입 소개 방식
const values: number[] = [1, 2, 3];
const values2: Array<number> = [1, 2, 3];

const data: [string, number] = [msg, size]; // 튜플 타입, 각 배열마다 인덱스 지정
data[0].substr(1);
data[1].substr(1); // 타입에러 발생, number에는 substr()이라는 메소드가 없음

console.log('typeof 123 =>', typeof 123); // number
console.log('typeof "abc" =>', typeof 'abc'); // string
console.log('typeof [1,2,3] =>', typeof [1, 2, 3]); // object
  • JS에서 배열은 결국 객체(Object)타입이다. 따라서 마지막 줄에 Object로 출력이 된다.

undefined, null, union 타입

let v1: undefined = undefined;
let v2: null = null;
v1 = 123; // Error이유: undefined 타입에 number타입을 지정했기 때문

let v3: number | undefined = undefined; // 유니온 타입
v3 = 123;

console.log('typeof undefined: ', typeof undefined); // undefined
console.log('typeof null: ', typeof null); // object
  • null은 type으로 존재하지 않고 object로 표현이 된다.

  • undefined와 null 타입은 다른 타입과 함께 유니온 타입으로 정의할 때 많이 사용된다.


문자열 리터럴과 숫자 리터럴 타입

let value: any;
value = 123;
value = '456`;
value = () => {};
  • any 타입은 모든 종류의 값을 허용한다.

  • 타입 정의가 안된 외부 패키지를 사용하는데 유용하다.

void, never 타입

function f1(): void { // 1. 아무것도 반환하지 않으니 void 타입
	console.log('hello');
}
function f2(): never { // 2.함수가 항상 비정상적으로 종료되므로 never타입
	throw new Error('some error');
}
function f3(): never { // 3. 함수가 종료되지 않으므로 never타입
	while(true) {
      
}
  • void 타입: 아무 값도 반환하지 않고 종료되는 함수의 반환 타입

  • never 타입: 예외로 인한 비정상적인 종료나 무한 루프 때문에 종료되지 않는 함수의 반환 타입

Object 타입

let v: object;
v = { name: 'abc' };

console.log(v.prop1); // 타입 에러 발생
  • 객체의 속성에 대한 정보가 없기 때문에 특정 속성값에 접근하면 타입 에러가 발생한다.

  • 속성 정보를 포함해서 타입을 정의하기 위해서는 뒤에 설명할 인터페이스(interface)를 사용해야 한다.

교차(intersection) 타입과 유니온 타입

let v1: (1 | 3 | 5) & (3 | 5 | 7);
v1 = 3;
v1 = 1; // 타입 에러

// 변수 v1의 타입은 3 | 5와 같다.
  • 변수 v1에는 3 또는 5가 아닌 값을 할당할 수 없다.

type 키워드로 타입에 별칭 주기

type Width = number | string;
let width: Width;
width = 100;
width = '100px';

enum(열거형) 타입

enum Fruit {
    Apple,
    Banana,
    Orange,	
}
const v1: Fruit = Fruit.Apple;
const v2: Fruit.Apple | Fruit.Banana = Fruit.Banana;
enum Fruit {
  Apple, // Q1
  Banana = 5,// Q2
  Orange, // Q3
}

console.log(Fruit.Apple, Fruit.Banana, Fruit.Orange); // 0, 5, 6
  • Q1: 열거형 타입의 첫 번째 원소에 값을 할당하지 않으면 자동으로 0이 할당된다.

  • Q2: 열거형 타입의 각 원소에 숫자 또는 문자열을 할당할 수 있다.

  • Q3: 명시적으로 값을 입력하지 않으면 이전 원소에서 1만큼 증가된 값이 할당된다.

  • 다른 타입과 달리 열거형 타입은 컴파일 후에도 관련된 코드가 남는다. 예를 들어, TS는 위의 예제 코드를 다음과 같이 컴파일한다.

var Fruit;
(function (Fruit) {
    Fruit[Fruit["Apple"] = 0] = "Apple"; // Q2
    Fruit[Fruit["Banana"] = 5] = "Banana";
    Fruit[Fruit["Orange"] = 6] = "Orange";
})(Fruit || (Fruit = {})); // Q1
console.log(Fruit.Apple, Fruit.Banana, Fruit.Orange); // 0, 5, 6
  • Q1: 열거형 타입은 객체로 존재한다.

  • Q2: 열거형 타입의 각 원소는 이름과 값이 양방향으로 매핑된다.

열거형 타입은 객체로 존재하기 때문에 해당 객체를 런타임에 사용할 수 있다. 다음은 열거형 타입의 객체를 사용하는 코드다.

enum Fruit {
  Apple,
  Banana = 5,
  Orange,
}

console.log(Fruit.Banana); // 5
console.log(Fruit.['Banana']) // 5
console.log(Fruit[5]) // Banana   // Q1
  • Q1: 각 원소의 이름과 값이 양방향 매핑 되어 있기 때문에 값을 이용해서 이름을 가져올 수 있다.

열거형 타입의 값으로 문자열 할당하기

var Language;
(function (Language) {
    Language["Korean"] = "ko";
    Language["English"] = "en";
    Language["Japanese"] = "jp";
})(Language || (Language = {}));
  • 열거형 타입의 원소에 문자열을 할당하는 경우에는 단방향으로 매핑된다. 이는 서로 다른 원소의 이름 또는 값이 같을 경우 충돌이 발생하기 때문이다.

열거형 타입을 위한 유틸리티 함수

  • 열거형 타입을 자주 사용한다면 몇 가지 유틸리티 함수를 만들어 사용하는게 좋다.

  • 다음은 특정 열거형 타입에서 원소의 개수를 반환하는 함수다.

function getEnumLength(enumObject: any) {
  const keys = Object.keys(enumObject);
  // enum의 값이 숫자이면 두 개씩 들어가므로 문자열만 계산한다.
  return keys.reduce((acc, key) => (typeof enumObject[key] === 'string' ? acc + 1 : acc), 0);
}
  • 원소가 숫자인 경우에는 양방향으로 매핑되기 때문에 주의해야 한다.

  • 객체의 속성값이 문자열인 경우만 계싼하면 열거형 타입에서 원소의 개수를 구할 수 있다.


  • 다음은 입력된 값이 열거형 타입에 존재하는 값인지 검사하는 함수다.
function isValidEnumValue(enumObject: any, value: number | string) {
  // 값이 숫자이면 양방향으로 매핑했는지 검사한다.
  if (typeof value === 'number') return !!enumObject[value];
  else {
    return Object.keys(enumObject)
      .filter((key) => isNaN(Number(key))) // number인 key를 판별해서 filter로 제거한 후
      .some((key) => enumObject[key] === value); // 해당 값이 존재하는지 판별한다.
  }
}
  • 다음은 앞에서 살펴본 getEnumLength 함수와 isValidEnumValue 함수를 사용하는 코드다.
enum Fruit {
  Apple,
  Banana,
  Orange,
}

enum Language {
  Korean = 'ko',
  English = 'en',
  Japanese = 'jp',
}

console.log(getEnumLength(Fruit), getEnumLength(Language)); // 3, 3
console.log('1 in Fruit', isValidEnumValue(Fruit, 1)); // true
console.log('5 in Fruit', isValidEnumValue(Fruit, 5)); // false
console.log('ko in langue: ', isValidEnumValue(Language, 'ko')); // true
console.log('Korean in Language: ', isValidEnumValue(Language, 'Korean')); // false
  • isValidEnumValue 함수는 서버로부터 받은 데이터를 검증할 때 유용하게 사용될 수 있다.

상수 열거형 타입

열거형 타입은 컴파일 후에도 남아있기 때문에 번들 파일의 크기가 불필요하게 커질 수 있다.

  • 열거형 타입의 객체에 접근하지 않는다면 굳이 컴파일 후에 객체로 남겨 놓을 필요는 없다.

  • 상수(const) 열거형 타입을 사용하면 컴파일 결과에 열거형 타입의 객체를 남겨 놓지 않을 수 있다.

const enum Fruit {
  Apple,
  Banana,
  Orange,
}

const enum Language {
  Korean = 'ko',
  English = 'en',
  Japanese = 'jp',
}

const lang: Language = Language.Korean;
  • 이를 컴파일한 결과는 다음과 같다.
const fruit = 0;
const lang = 'ko';
  • 열거형 타입의 객체를 생성하는 코드가 보이지 않는다. 열거형 타입이 사용된 코드는 원소의 값으로 대체되므로 코드가 상당히 간소화된다.

  • 하지만 상수 열거형 타입을 모든 경우에 쓸 수 있는 것은 아니다. 열거형 타입을 상수로 정의하면 열거형 타입의 객체를 사용할 수 없다.

const enum Fruit {
  Apple,
  Banana,
  Orange,
}

function getEnumLength(enumObject: any) {
  const keys = Object.keys(enumObject);
  // enum의 값이 숫자이면 두 개씩 들어가므로 문자열만 계산한다.
  return keys.reduce((acc, key) => (typeof enumObject[key] === 'string' ? acc + 1 : acc), 0);
}

console.log(getEnumLength(Fruit)); // TypeError
  • 열거형 타입을 상수로 정의하면 열거형 타입의 객체를 사용할 수 없다.

0개의 댓글