타입(type)
값과 이 값으로 할 수 있는 일의 집합
타입 검사기(typechecker)를 이용해 유효하지 않은 동작이 실행되는 일을 예방하는 것이다. 여러분이 어떤 타입을 어떻게 사용하는지를 통해 타입 확인자는 특정 동작이 유효한지 아닌지 판단 할 수 있다.
squareOf
라는 함수는 숫자를 파라미터로 받음이 명확하며, 숫자가 아닌 다른 타입을 전달하면 유효하지 않은 작업을 수행하게 된다. 따라서 매개변수의 타입을 명시하도록 하자
이제 숫자가 아닌 타입을 건네 squareOf
를 호출하면 타입스크립트가 바로 에러를 발생시킨다. 타입스크립트란 '특정 타입만 와야 할 때 이를 명시할 수 있는 언어' 라는 사실만 이해하자
타입스크립트가 지원하는 각각의 타입을 살펴보면서 각 타입이 무엇을 포함할 수 있는지, 어떤 동작을 수행할 수 있는지를 살펴보자.
any는 타입들의 대부라고 할 수 있다.
any로 뭐든지 할 수 있지만 꼭 필요한 상황이 아니라면 사용하지 않는 것이 좋다.
이유가 뭘까 ? 🤔
타입이란 값과 값으로 수행할 수 있는 작업의 집합이다. any는 모든 값의 집합이므로 any는 모든 것을 할 수 있다. any는 모든 값의 집합이므로 any는 모든 것을 할 수 있다. any를 사용하면 값이 자바스크립트처럼 동작하기 시작하면서 타입 검사기라는 마법이 더 이상 작동하지 않게 된다.
✅ TSC 플래그 : noImplicitAny
타입스크립트의 기본 설정은 자유를 허용하므로 any로 추론되는 값을 발견하더라도 예외를 발생시키지 않는다. 그러니 암묵적인 any가 나타났을 때 예외를 일으키고 싶다면 tsconfig.json 파일에서 noImplicitAny 플래그를 활성화 하자.
타입을 미리 알 수 없는 어떤 값이 있을 때 any 대신 unknown을 사용하자.
any처럼 unknown도 모든 값을 대표하지만, unknown의 타입을 검사해 정제(refine)하기 전까지는 타입스크립트가 unknown 타입의 값을 사용할 수 없게 강제한다.
타입스크립트가 무언가의 타입을 unknown 이라고 추론하는 상황은 없다. unknown 타입을 사용하고자 한다면 개발자가 명시적으로 설정해야 한다.
unknown 타입이 아닌 값과 unknown 타입인 값을 비교할 수 있다.
하지만 unknown 값이 특정 타입이라고 가정하고 해당 타입에서 지원하는 동작을 수행할 수 없다. 먼저 타입스크립트에게 해당 값이 특정 타입임을 증명해야 한다.
boolean(불) 타입은 true(참), false(거짓) 두 개의 값을 갖는다. 이 타입으로는 비교 연산(==, ===, ||, &&, ?)과 반전(!) 연산을 할 수 있을 뿐 많은 연산을 지원하지 않는다.
타입 리터럴(type literal)
오직 하나의 값을 나타내는 타입
number 타입은 모든 숫자(정수, 소수, 양수, 음수, Infinitym NaN 등)의 집합이다. number 타입에는 덧셈(+), 뺄셈(-), 모듈로(%), 비교(<) 등의 숫자 관련 연산을 수행할 수 있다.
자바스크립트와 타입스크립트에 새로 추가된 타입으로, 이를 이용하면 라운딩 관련 에러 걱정 없이 큰 정수를 처리할 수 있다. numer는 2의 53승까지의 정수를 표현할 수 있지만 bigint를 이용하면 이보다 큰 수도 표현할 수 잇다.
✅ 일부 자바스크립트 엔진은 bigint를 자체적으로 지원하지 않는다. 따라서 응용프로그램에서 bigint를 사용하려면 먼저 대상 플랫폼이 이를 지원하는지 확인하자.
string은 모든 문자열의 집합으로 연결(+), 슬라이스(.slice) 등의 연산을 수행할 수 있다.
boolean과 number 처럼 string 타입도 네 가지 방법으로 선언할 수 있으며 가능하다면 타입스크립트가 string 타입을 추론하도록 두는 것이 좋다.
symbol(심벌)은 ES2015에 새로 추가된 기능이다. 실무에서는 심벌을 자주 사용하지 않는 편이며 객체와 맵에서 문자열 키를 대신하는 용도로 사용한다. 심벌 키를 사용하면 사람들이 잘 알려진 키만 사용하도록 강제할 수 있으므로 키를 잘못 설정하는 실수를 방지한다.
자바스크립트에서 Symbol('a')는 주어진 이름으로 새로운 symbol을 만든다는 의미다.
만들어진 symbol은 고유(unique) 하여 다른 symbol과 == 또는 ===로 비교했을 때 같지 않다고 판단된다.
타입스크립트의 객체(object) 타입은 객체의 형태(shape)를 정의한다. 재미있게도 객체 타입만으로는 ({}로 만든) 간단한 객체와(new를 사용해 만든) 복잡한 객체를 구분할 수 없다. 이는 자바스크립트가 구조 기반 타입(structural type)을 갖도록 설계되었기 때문이다.
구조 기반 타입화
구조 기반 타입화에서는 객체의 이름에 상관없이 객체가 어떤 프로퍼티를 갖고 있는지를 따진다.(이름 기반 타입에서는 이름을 따진다). 일부 언어에서는 덕 타이핑(duck typing)이라고 한다.
타입스크립트에서 객체를 서술하는 데 타입을 이용하는 방식은 여러가지다.
✔️ 첫번째 방법은 object로 선언하는 것이다.
명시적으로 정의하지 않고 타입스크립트가 추론하도록 하면 어떨까?
✔️ 객체 리터럴 문법을 통해 객체 타입을 만드는 두 번째 방법
✅ 타입스크립트에서 객체를 정의하는 방법 네가지 요약
값이 있으면 값의 타입이 무엇인지에 따라 수행할 수 있는 연산이 달라진다.
ex) 예를 들어 +로 두 숫자를 더하거나 .toUpperCase로 문자열을 대문자로 만들 수 있다.
값뿐만 아니라 타입에도 어떤 동작을 수행할 수 있다. 이제 타입 수준에서 수행할 수 있는 몇 가지 동작을 소개하려 한다.
✔️ 타입 별칭
(let, const, var로) 변수를 선언해서 값 대신 변수로 칭하듯이 타입 별칭으로 타입을 가리킬 수 있다.
Age는 number다. 타입 별칭을 이용하면 Persom 형태를 조금 더 이해하기 쉽게 정의 할 수 있다. 타입스크립트는 별칭을 추론하지 않으므로 반드시 별칭의 타입을 명시적으로 정의해야 한다.
자바스크립트 변수 선언과 마찬가지로 하나의 타입을 두 번 정의할 수는 없다.
let과 const처럼 타입 별칭도 블록 영역에 적용된다.
✔️ 유니온과 인터섹션 타입
타입스크립트는 타입에 적용할 수 있는 특별한 연산자인 유니온 (|)과 인터섹션 (&)을 제공한다. 타입은 집합과 비슷하므로 집합처럼 연산을 수행할 수 있다.
실전에서는 대게 인터섹션보다 유니온을 자주 사용한다.
자바스크립트처럼 타입스크립트 배열도 연결(concatenation), 푸시(pushing), 검색(searching), 슬라이스(slicing) 등을 지원하는 특별한 객체다.
✅ 타입스크립트는 T[], Array<T> 라는 두 가지 배열 문법을 지원한다. 성능, 의미상 두 표현은 같다. 이 책에서는 더 간결한 T[] 문법을 사용하지만 여러분은 자신의 취향대로 원하는 분법을 사용하기 바란다.
튜플(tuple)은 배열의 서브타입이다. 튜플은 길이가 고정되었고, 각 인덱스의 타입이 알려진 배열의 일종이다. 다른 타입과 달리 튜플은 선언할 때 타입을 명시해야 한다.
튜플은 이형(heterogeneous) 배열을 안전하게 관리할 뿐 아니라 배열 타입의 길이도 조절한다. 이런 기능을 잘 활용하면 순수 배열에 비해 안전성을 높일 수 있으므로 튜플 사용을 권장한다.
✔️ 읽기 전용 배열과 튜플
일반 배열은 가변(mutable)인 반면, 상황에 따라서는 불변(immutable)인 배열이 필요할 수 있다.
가변(mutable)? 불변(immutable)? 🤔
- 가변(mutable) : .push, .splice, 갱신 등의 작업을 자유롭게 수행할 수 있는
- 불변(immutable) : 한번 배열을 만들어 내용을 추가한 이후로는 내용을 바꿀 수 없는
타입스크립트는 readonly 배열 타입을 기본으로 지원하므로 이를 이용해 불변 배열을 바로 만들 수 있다. 읽기 전용 배열은 일반 배열과 같지만, 내용을 갱신할 수 없다는 점만 다르다.
읽기 전용 배열은 바꿀 수 없으므로 코드를 쉽게 이해할 수 있는 장점이 있지만 결국 자바스크립트 배열로 구현한 것이다. 즉, 스프레드(...)나 .slice 등으로 배열을 조금만 바꿔도 우선 원래 배열을 복사해야 하므로, 주의하지 않으면 응용 프로그램의 성능이 느려질 수 있다.
자바스크립트는 null, undefined 두 가지 값으로 부재를 표현한다. 타입스크립트도 두 가지 값 모두를 지원한다. 타입스크립트에서는 이 값을 무엇이라 부를까? 똑같이 null undefined 라고 부른다.
undefined는 아직 정의하지 않았음을 의미하는 반면 null은 값이 없다는 의미다.
void는 명시적으로 아무것도 반환하지 않는 함수의 반환 타입(ex: console.log)을 가리키며 never는 절대 반환하지 않는 함수 타입(ex: 예외를 던지거나 영원히 실행되는)을 가리킨다.
unknown이 모든 타입의 상위 타입이라면 never는 모든 타입의 서브타입이다. 즉, 모든 타입에 never를 할당할 수 있으며 never 값은 어디서든 안전하게 사용할 수 있다.
해당 타입으로 사용할 수 있는 값을 열거하는 기법이다. 열거형은 키를 값에 할당하는, 순서가 없는 자료구조다. 키가 컴파일 타임에 고정된 객체라고 생각하면 쉽다. 따라서 타입스크립트는 키에 접근할 때 주어진 키가 실제 존재하는지 확인할 수 있다.
열거형의 이름은 단수 명사로 쓰고, 첫 문자는 대문자로 하는 것이 관례다. 키도 앞 글자를 대문자로 표시한다.
타입스크립트는 자동으로 열거형의 각 멤버에 적절한 숫자를 추론해 할당하지만, 값을 명시적으로 설정할 수도 있다.
✅ 열거형을 안전하게 사용하는 방법은 까다로우므로 열거형 자체를 멀리 할 것을 권한다. 타입스크립트에는 열거형을 대체할 수단이 많다.
타입스크립트는 다양한 내장 타입을 제공한다. 타입스크립트가 값의 타입을 추론하도록 하거나 값을 추론하도록 하거나 값의 타입을 명시할 수 있다.
let과 var를 사용하면 일반적인 타입을 추론하는 반면, const를 이용하면 더 구체적인 타입을 추론하게만든다.