프론트엔드/TypeScript

[TypeScript] 타입 종류

TypeScript에 대해 본격적인 포스팅을 남기고자 합니다.

이 글을 통해 먼저 TypeScript의 기본 타입의 종류에 대해 알아보겠습니다.

 


Boolean

Boolean 타입은 참(true)과 거짓(false) 값을 가질 수 있습니다.

let isBoolean: boolean;
let isDone: boolean = false;

 


Number

Number 타입은 모든 부동 소수점 값을 가질 수 있습니다.

ES6의 2진수 및 8진수 리터럴 값 또한 지원합니다.

let num: number;
let integer: number = 6;
let float: number = 3.14;
let hex: number = 0xf00d;  // 61453
let binary: number = 0b1010;  // 10
let octal: number = 0o744;  // 484
let infinity: number = Infinity;
let nan: number = NaN;

 


String

String 타입은 작은따옴표('), 큰 따옴표(")로 표현된 문자열을 가질 수 있습니다.

ES6의 템플릿 문자열 또한 지원합니다.

let str: string;
let red: string = 'Red';
let green: string = "Green";
let myColor: string = `My color is ${red}.`;

 


Array

Array 타입은 두 가지 방법으로 선언할 수 있습니다.

타입 뒤에 []를 붙이거나 Array<T> 형태의  제네릭 배열 타입을 사용합니다

let fruits: string[] = ['Apple', 'Banana', 'Mango'];
let fruits: Array<string> = ['Apple', 'Banana', 'Mango'];

let oneToSeven: number[] = [1, 2, 3, 4, 5, 6, 7];
let oneToSeven: Array<number> = [1, 2, 3, 4, 5, 6, 7];

 

유니언 타입과 함께 사용할 수도 있습니다.

let array: (string | number)[] = ['Apple', 1, 2, 'Banana', 'Mango', 3];
let array: Array<string | number> = ['Apple', 1, 2, 'Banana', 'Mango', 3];

 

인터페이스(Interface)나 커스텀 타입(Type)과 함께 사용할 수도 있습니다.

interface User {
  name: string,
  age: number,
  isValid: boolean
}

let userArr: User[] = [
  {
    name: 'Neo',
    age: 85,
    isValid: true
  },
  {
    name: 'Lewis',
    age: 52,
    isValid: false
  },
  {
    name: 'Evan',
    age: 36,
    isValid: true
  }
];

 

읽기 전용 배열을 만들 수도 있습니다.

readonly 키워드나 ReadonlyArray 타입을 사용하면 됩니다.

let arr: readonly number[] = [1, 2, 3, 4];
let arr: ReadonlyArray<number> = [1, 2, 3, 4];

arr[0] = 123;  // Error
arr.push(123);  // Error

 


Tuple

Tuple 타입은 배열과 매우 유사합니다.

하지만 배열과 달리 정해진 타입의 고정된 길이의 배열을 나타냅니다.

let tuple: [string, number];

tuple = ['a', 1];
tuple = ['a', 1, 2];  // Error
tuple = [1, 'a'];  // Error

 

다만 Tuple 타입은 할당되는 순간에만 유효합니다.

.push() 또는 .splice() 를 통해 배열이 변경되는 행위는 막을 수 없습니다.

(readonly 키워드를 사용해 읽기 전용 튜플을 생성할 수도 있습니다.)

tuple.push(30);  // OK

 


Enum

Enum(열거형) 타입은 숫자 혹은 문자열 값 집합에 이름(Member)을 부여할 수 있습니다.

값의 종류가 일정한 범위로 정해져 있는 경우 유용합니다.

기본 값은 0으로 시작하며 값이 1씩 증가합니다.

enum Week {
  Sun,  // = 0
  Mon,  // = 1
  Tue,  // = 2
  Wed,  // = 3
  Thu,  // = 4
  Fri,  // = 5
  Sat   // = 6
}

 

수동으로 값을 변경하면 변경한 부분부터 1씩 증가합니다.

enum Week {
  Sun,  // = 0
  Mon = 10,
  Tue,  // = 11
  Wed,  // = 12
  Thu,  // = 13
  Fri,  // = 14
  Sat   // = 15
}

 

🔎 Reverse Mapping (역방향 매핑)

Enum 타입은 역방향 매핑을 지원합니다.

즉 멤버로 값에 접근할 수도 있고, 값으로 멤버에 접근할 수도 있습니다.

console.log(Week.Sun); // 0
console.log(Week['Sun']); // 0
console.log(Week[0]); // 'Sun'

 


Any

Any 타입은 모든 타입을 의미합니다.

즉 어떤 타입의 값도 할당할 수 있습니다.

let any: any = 123;
any = 'play game';
any = {};
any = null;

 

🔎 Unknown

TypeScript는 Any 타입의 사용을 지양하며 타입을 명시할 것을 권장합니다.

하지만 외부 자원을 활용할 때 타입을 단언하기 힘든 경우 종종 Any 타입이 필요할 수 있습니다.

이때 Unknown 타입이 대안이 될 수 있습니다.

 

Unknown 타입은 안전한 Any 타입이라 불립니다.

즉 Any 타입과 마찬가지로 모든 타입의 값이 할당될 수 있습니다.

(다만 Unknown 타입의 변수는 Any 타입을 제외한 다른 타입에는 할당될 수 없습니다.)

let variable: unknown

let anyType: any = variable
let booleanType: boolean = variable // Error

 

그리고 Unknown 타입으로 선언된 변수는 아래와 같은 특징들을 가집니다.

  • 프로퍼티에 접근할 수 없음
  • 메서드를 호출할 수 없음
  • 인스턴스를 생성할 수도 없음
let variable: unknown

variable.foo.bar // Error
variable[0] // Error
variable.trigger() // Error
variable() // Error
new variable() // Error

 


Never

Never 타입은 어떠한 값도 가질 수 없는 타입을 나타냅니다.

주로 허용하지 않는 상황을 구현할 때 Never 타입을 활용한다고 합니다.

function error(message: string): never {
    throw new Error(message);
}

 


Object

Object 타입은 객체, 배열, 함수 등 모든 객체 타입을 가질 수 있습니다.

let obj: object = {};
let arr: object = [];
let func: object = function () {};
let date: object = new Date();

 

하지만 Object 타입을 활용하는 것보다 객체 속성을 개별적으로 지정하는 것을 권장합니다.

Object 타입은 모든 객체 타입을 포함하기 때문에 정확한 의미를 표현하기 어렵습니다.

let userA: { name: string, age: number } = {
  name: 'SO',
  age: 123
};

let userB: { name: string, age: number } = {
  name: 'SO',
  age: false,  // Error
  email: 'thesecon@gmail.com'  // Error
};

 

객체 타입이 반복적으로 사용되면 Interface나 Type을 사용하는 것이 좋습니다.

interface User {
  name: string,
  age: number
}

let user: User = {
  name: 'SO',
  age: 123
};

let userB: IUser = {
  name: 'SO',
  age: false, // Error
  email: 'so@gmail.com' // Error
};

 


Null과 Undefined

null과 undefined는 값 그 자체가 타입의 이름과도 같습니다.

그리고 null과 undefined는 모든 타입의 하위 타입입니다.

즉 number 등 어떤 타입에도 null과 undefined를 할당할 수 있습니다.

let num: number = undefined;
let str: string = null;

 

하지만 이러한 방식은 의도치 않은 에러를 발생시킬 수 있습니다.

strictNullchecks 옵션을 통해 null과 undefined 값이 다른 타입에 할당하지 못하게 할 수 있습니다.

 


Void

Void는 일반적으로 함수가 값을 반환하지 않을 때 사용합니다.

function hello(msg: string): void {
  console.log(`Hello ${msg}`);
}

 


Union

Union 타입은 | 를 통해 2개 이상의 타입을 허용할 수 있습니다.

let union: (string | number);

union = 'Hello type!';
union = 123;
union = false; // Error