TypeScript는 간단하게 말해서 타입을 강제하는 JavaScript라고 할 수 있습니다.
JavaScript에 대한 지식이 있는 분이 읽는다는 가정하에 작성합니다.
TypeScript 공식문서의 스펙을 보면서 생각한 차이에 대해 핵심을 정리한 글입니다.
let isDone: boolean = false;
let decimal: number = 6;
이런 식으로 변수자체 타입을 정해주어야합니다.
let color: string = 'bluer';
color = 'red';
선언 후에 재할당시에는 JavaScript와 같습니다.
배열의 경우엔
let list1: number[] = [1,2,3];
let list2: Array<number> = [1,2,3];
두가지 방법으로 작성할 수 있습니다.
let x: [string, number];
x = ["hello", 10];
이런식으로 배열의 사이즈와 각 인덱스의 타입을 강제할 수 있습니다. 사이즈를 벗어난 인덱스를 참조하거나 각 인덱스의 타입과 다른 타입을 재할당 할 수 없습니다.
JavaScript의 객체와 비슷하며,
숫자 값에 알기 쉬운 네이밍을 주는 방법입니다.
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
console.log(c); // output: 1
Red, Green, Blue는 순서대로 0,1,2의 밸류를 가지고 있습니다.
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green;
console.log(c); // output: 2
시작 값을 1로 바꾸어주면 뒤의 값들도 같이 바뀝니다.
또한, 아래와 같은 방식으로 각각 지정해 줄 수도 있습니다.
enum Color {Red = 1, Green = 2, Blue = 4}
반대로, 값으로부터 키 값을 구할 수도 있습니다.
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];
console.log(colorName); // Displays 'Green' as its value is 2 above
참고로, 여기서 Color[2]는 Color의 2번째 인덱스가 아니라, 2라는 밸류를 갖고있는 키값을 의미합니다.
동적인 타입을 가지는 변수(타입을 하나로 고정하지 않을 변수)는 Any라는 타입을 씁니다.
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
또한, 배열의 원소들의 타입이 여러가지일 경우에는
let list: any[] = [1, true, "free"];
list[1] = 100;
이런 방식으로 지정 가능합니다.
Void는 비어있다는 의미입니다.
TypeScript는 function의 parameter와 return value도 타입을 명시해주어야하는데,
주로 return value가 없을 때 Void를 활용합니다.
function warnUser(): void {
console.log("This is my warning message");
}
변수에도 void 타입을 강제할 수 있지만, null과 undefined이외엔 할당할 수 없기때문에, 별로 유용하지 않습니다.
let unusable: void = undefined;
unusable = null
참고로, --strictNullChecks
가 설정이 되어있지 않은 경우에만 가능합니다.
undefined와 null도 각자의 타입을 가집니다.
let u: undefined = undefined;
let n: null = null;
이것 또한 null이나 undefined값만 가질 수 있기 때문에 사용할 일이 적을 수 있습니다.
기본적으로 null과 undefined는 모든 타입의 서브타입이기 때문에 다른 타입에도 null이나 undefined를 할당할 수 있습니다.
그러나 --strictNullChecks
flag를 사용하면 null과 undefined는 any타입과 스스로의 타입이외엔 할당할 수 없습니다. (undefined는 void타입에도 할당 가능합니다)
string, null or undefined 타입을 넘기고 싶다면, string | null | undefined 타입을 이용하면 됩니다.
값을 리턴하지 않을 때 사용합니다.
// Function returning never must have unreachable end point
function error(message: string): never {
throw new Error(message);
}
// Inferred return type is never
function fail() {
return error("Something failed");
}
// Function returning never must have unreachable end point
function infiniteLoop(): never {
while (true) {
}
}
declare function create(o: object | null): void;
create({ prop: 0 }); // OK
create(null); // OK
create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error
any로 선언해두고 참조할 때 타입을 assert합니다.(단언하다라는 뜻인데, 대충 string일거라고 판단하겠다는 뜻입니다.)
그래서 someValue는 any 타입이지만 string타입의 메소드인 .length를 사용할 수 있습니다.
하지만, 실제로 string이 아닐 경우엔 에러를 출력하지않고, 강제로 타입 변환이 수행하지는 않습니다.)
두가지 방식으로 사용할 수 있습니다.
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
실제로 사용할땐 사실 void만 사용하고 있긴합니다만...
never나 void나 결국 둘다 리턴하지 않는데 타입을 나눈 이유가 있을까요?