코드를 작성하다 보면 잘못된 타입의 변수를 전달해 주거나, 오타로 인해 에러가 발생할 때가 있다. 이런 경우, 규모가 작은 프로젝트라면 쉽게 원인을 찾을 수 있다. 그러나, 프로젝트가 크다면, 어디가 잘못되었는지를 알기 힘들다. 이것을 해결하기 위한 자바스크립트 슈퍼셋, 타입스크립트가 등장했다.
이전까지는 타입스크립트를 사용했지만, interface
를 사용한 기본적인 변수들의 타입 지정에 불과했다. 타입스크립트를 제대로 공부해 보기로 했다.
타입 지정을 해줄 때는 기본적으로 변수 뒤에 콜론과 함께 소문자로 된 타입을 지정해 준다.
function add(n1: number, n2: number) {
return n1 + n2;
}
타입스크립트에는 자바스크립트가 기본적으로 제공하는 숫자, 문자열, 불리언 타입 외에, 자바스크립트에 존재하지 않는 다른 타입들도 존재한다.
튜플은 배열과 유사하지만, 타입과 길이가 고정된다.
role: [number, string]
위와 같은 방식으로 튜플을 선언해 주면, 겉보기에는 배열과 같지만, 배열의 길이를 바꾸거나, 각 요소의 타입을 바꿀 수 없다.
길이가 2개이고, 첫 번째 요소는 숫자, 두 번째는 문자열인 배열만 들어갈 수 있다.
잘못된 타입(e.g., boolean)을 넣어주면 에러가 발생하기는 하지만, 그러나 위 배열에 push 등의 메서드를 사용하여 길이를 변화시키거나, 숫자나 문자열 타입을 추가하여도 에러가 발생하지 않는다.
타입스크립트가 에러를 잡지 못하기 때문인데, 이러한 에러는 타입스크립트 3.4에서 새롭게 등장한 as const
를 사용하면 된다.
Enum 타입도 타입스크립트에만 존재하는 타입이다. 특정 요소를 숫자로 구분하는 변수를 지정할 수 있다. 그러나 어떤 숫자가 어떤 요소를 뜻하는지 잊어버릴 수 있다. 이를 위해 요소에 라벨을 달아주는 것이 enum
타입이다.
자바스크립트 환경에서 전역 변수를 선언하고 그에 접근할 수 있지만, 이를 enum타입으로 대체할 수 있다.
const ADMIN = 0;
const USER = 1;
위처럼 선언된 것을
이런 식으로 선언하면 자동으로 각 요소는 0과 1을 가지게 된다. 그리고 개발자도 숫자로 작성된 기억하기 어려운 요소 대신, 문자열로 쉽게 접근할 수 있다.
각 요소는 0부터 순서대로 지정되지면 등호를 사용하여 원하는 숫자를 지정할 수 있다.
any는 가장 유연한 타입이다. 이 타입을 지정하면 어떤 타입의 값도 들어올 수 있다. anyscript
any만 사용하면 타입스크립트를 사용하는 의미가 없기 때문에, 사용을 지양하는 것이 좋다.
유니언 타입은 변수에 하나 이상의 타입을 지정하고 싶을 때 사용할 수 있다. 만약 특정 배열에 숫자와 문자열이 있다면, 다음과 같이 타입을 지정해줄 수 있다.
const arr: (number | string)[] = ["a", 410, "b"];
리터럴 타입은 해다 변수가 정확히 어떤 값을 가져야하는지 지정해 주는 것이다.
age: 'minor' | 'adult'
여러 개의 타입을 한 번에 선언해 줄 수 있다. type
을 사용하여 생성한 타입은, 여러 번 재사용할 수 있고 필요에 따라 확장이 가능하다.
type human = {
name: string;
age: number;
...
}
함수의 리턴 값에도 타입을 지정해 줄 수 있다.
const add = (num1: number, num2: number): number => {
return num1 + num2;
};
그러나 이 경우는 명시적으로 지정하기 보다는 타입스크립트가 스스로 추론할 수 있도록 하는 것이 좋다.
아무것도 반환하지 않는 함수의 리턴 타입은 void
이다.
함수를 다른 변수에 지정했을 때, 타입을 지정하는 법을 알아보자. 아래처럼 add함수를 addNumber에 지정한 다음,
const add = (num1: number, num2: number) => {
return num1 + num2;
};
const minus = (num1: number, num2: number) => {
console.log(num1 - num2);
};
let addNumbers;
addNumbers = add;
addNumbers = 123;
console.log(addNumbers);
// 위 처럼 숫자 타입을 지정해도 아무런 에러가 발생하지 않는다. 여기에 함수 타입을 지정할 수 있는데, 이 경우는 `함수가 할당되었는가`만 판단하기 때문에, add의 구조로 되어있지 않은 함수를 지정해도 에러가 발생하지 않는다.
let addNum: Function;
addNum = minus;
// 이런 경우에는 인수와 리턴 값을 전달해 주어야 한다.
let addNumber: (a: number, b: number) => number;
addNumber = add;
addNumber = minus; // 에러 발생
console.log(addNumber("123", 123)); // 에러 발생
console.log(addNumber(123, 123));
콜백 함수에도 타입을 지정할 수 있다. 그러나, 콜백 함수에서 아무것도 리턴하지 않는다고 지정했음에도 콜백 함수 내에서 결과값을 리턴에도 에러가 발생하지 않는다.
const addAndHandle = (n1: number, n2: number, cb: (num: number) => void) => {
const res = cb(n1 + n2);
console.log(res);
};
addAndHandle(123, 321, (result) => {
console.log(result);
return result; // 에러가 발생하지 않음
});
unknown 타입은 어떤 타입이 들어올 지 모로는 상황에 사용할 수 있다. any
타입과 유사해 보이지만 몇 가지 차이점이 있다.
let variable: unknown;
let me: string;
variable = 1;
variable = "123";
me = variable;
if (typeof variable === "string") {
me = variable;
}
위에서 variable에는 문자열이 할당되어 있고, me의 타입은 문자열을 받아야 한다. variable의 타입이 any인 경우에는 아무런 에러도 발생하지 않는다. 그러나 unknown타입인 variable은 me에 할당할 수 없다. unknown타입을 다른 변수에 할당하기 위해서는 추가로 타입 검사가 필요하다.