Any
앱을 만들 때 아직 잘 모르는 타입을 표현해야 할 때가 있다. 이 값은 사용자로부터 받은 데이터나 서드 파티 라이브러리 같은 동적인 컨텐츠에서 올 수도 있다. 이때 타입 검사를 하지 않고, 해당 값이 컴파일 과정에서 통과되길 원한다. 이를 위해 any 타입을 사용한다. 하지만 이 타입은 최대한 쓰지 않는 게 좋다. 그래서 noImplicitAny라는 옵션을 주면 any를 썼을 때 오류가 뜨게 한다.
let something: any = "Hello World!";
something = 23;
something = true;
let arr: any[] = ["John", 212, true];
arr.push("Smith");
console.log(arr); //Output: [ 'John', 212, true, 'Smith' ]
Union
union 타입은 변수 또는 함수 매개변수에 대해 둘 이상의 데이터 유형을 사용하게 한다.
let code: (string | number);
code = 123; // OK
code = "ABC"; // OK
code = false; // Compiler Error
let empId: string | number;
empId = 111; // OK
empId = "E111"; // OK
empId = true; // Compiler Error
Tuple
TypeScript에서는 배열 타입을 특수 형태로 사용할 수 있는 tuple 타입을 지원한다. tuple에 명시적으로 지정된 형식에 따라 아이템 순서를 설정해야 하고, 추가되는 아이템 또한 tuple에 명시된 타입만 사용 가능하다. 튜플의 경우 'number | string'은 숫자와 문자열 값만 저장할 수 있다.
var employee: [number, string] = [1, "Steve"];
var person: [number, string, boolean] = [1, "Steve", true];
var user: [number, string, boolean, number, string]; // declare tuple variable
user = [1, "Steve", true, 20, "Admin"]; // initialize tuple variable
1) 배열 Tuple
var employee: [number, string][];
employee = [[1, "Steve"], [2, "Bill"], [3, "Jeff"]];
2) Tuple에 요소 추가
var employee: [number, string] = [1, "Steve"];
employee.push(2, "Bill");
console.log(employee); //Output: [1, 'Steve', 2, 'Bill']
3) 에러가 발생하는 경우
employee.push(true)
enum
enum은 enumerated type(열거형)을 의미한다. enum은 값들의 집합을 명명하고 이를 사용하도록 만든다. 여기에서는 PrintMedia라 불리는 집합을 기억하기 어려운 숫자 대신 친숙한 이름으로 사용하기 위해 enum을 활용할 수 있다. 열거된 각 PrintMedia는 별도의 값이 설정되지 않은 경우 기본적으로 0부터 시작한다.
enum PrintMedia {
Newspaper, // 0
Newsletter, // 1
Magazine, // 2
Book // 3
}
아래 코드에서 mediaType 변수에 할당된 값은 3이다. 설정된 PrintMedia 열거형 데이터의 Book의 값이 숫자 3이기 때문이다.
let mediaType: number = PrintMedia.Book // 3
enum에 설정된 아이템에 값을 할당할 수도 있다. 값이 할당되지 않은 아이템은 이전 아이템의 값에 +1된 값이 설정된다.
enum PrintMedia {
Newspaper = 1,
Newsletter = 50,
Magazine = 55,
Book // 55 + 1
}
아래 코드에서 mediaType 변수에 할당된 값은 56이다. 설정된 PrintMedia 열거형 데이터의 Book의 값이 숫자 56이기 때문이다.
let mediaType: number = PrintMedia.Book // 56
enum 타입의 편리한 기능으로 숫자 값을 통해 enum 값의 멤버 이름을 도출할 수 있다.
let type: string = PrintMedia[55] // 'Magazine'
또한 어떠한 언어 코드를 정의하는 코드를 작성할 때 언어의 집합을 만들 때도 enum을 사용할 수 있다.
export enum LanguageCode {
korean = 'ko',
english = 'en',
japanese = 'ja',
chinese = 'zh',
spanish = 'es',
}
const code: LanguageCode = LanguageCode.english
이렇게 enum을 이용해 언어 집합을 만들어주면 어떤 코드가 어떤 나라의 언어 코드가 무엇인지 알지 못해도 쉽게 코드를 작성해줄 수 있고 코드를 읽는 사람 입장에서도 가독성이 높아지게 된다.
let LanguageCode = {
korean : 'ko',
english : 'en',
japanese : 'ja',
chinese : 'zh',
spanish : 'es',
}
이렇게 보면 enum과 JS의 object를 사용하는 것과 별 차이가 없어 보인다. 사실 enum은 그 자체로 객체이기도 하다. 따라서,
- Object.keys(LanguageCode)를 하면 실제 키 값이 배열에 담겨 나온다. → ['korean', 'english']
- Object.values(LanguageCode) 를 하면 value 값이 → ['ko', 'en']
enum과 객체의 차이는 다음과 같다.
- object는 코드 내에서 새로운 속성을 자유롭게 추가할 수 있지만, enum은 선언할 때 이후에 변경할 수 없다.
- object의 속성 값은 JS가 허용하는 모든 타입이 올 수 있지만, enum의 속성 값으로는 문자열 혹은 숫자만 허용된다.
Void
Java와 같은 언어와 유사하게 데이터가 없는 경우 void가 사용된다. 예를 들어 함수가 값을 반환하지 않으면 반환 유형으로 void를 지정할 수 있다. 타입이 없는 상태이며, any와 반대 의미를 가진다. void 소문자로 사용해야 하며, 주로 함수의 리턴이 없을 때 사용하면 된다.
function sayHi(): void {
console.log('Hi!')
}
let speech: void = sayHi();
console.log(speech); //Output: undefined
Never
TypeScript는 절대 발생하지 않을 값을 나타내는 새 Type never를 도입했다. Never 유형은 어떤 일이 절대 일어나지 않을 것임이 확실할 때 사용된다. 일반적으로 함수의 리턴 타입으로 사용된다. 함수의 리턴 타입으로 never가 사용될 경우, 항상 오류를 리턴하거나 리턴 값을 절대로 내보내지 않음을 의미한다. 이는 무한 루프(loop)에 빠지는 것과 같다.
function throwError(errorMsg: string): never {
throw new Error(errorMsg);
}
function keepProcessing(): never {
while (true) {
console.log('I always does something and never ends.')
}
}
Void 와 Never의 차이
Void 유형은 값으로 undefind 혹은 null 값을 가질 수 있으며 Never는 어떤 값도 가질 수 없다.
let something: void = null;
let nothing: never = null; // Error: Type 'null' is not assignable to type 'never'
TypeScript에서 값을 Return하지 않는 함수는 실제로 undefined를 반환한다.
function sayHi(): void {
console.log('Hi!')
}
let speech: void = sayHi();
console.log(speech); // undefined
위의 예에서 볼 수 있듯이 sayHi 함수는 반환 유형이 void인 경우에도 내부적으로 undefined를 반환하기 때문에 speech는 undefined가 된다. Never 유형을 사용하는 경우 void는 Never에 할당할 수 없기 때문에 Speech:never는 컴파일 시간 오류를 발생시킨다.