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