위의 예시를 보면(타입스크립트 코드), 위에는 num이라는 변수의 타입을 명시적으로 표현해주지 않은 것이고, 아래는 명시적으로 넘버 타입을 표시해준 부분이다. 이 때, 주석 처리한 부분을 보면, num이라는 변수에 'string'이라는 문자열 타입의 자료를 할당하려했는데, 두 경우 모두 에러가 난다. 이처럼 타입스크립트는 num이라는 변수의 타입을 최초 할당시에 추론하여 알아낼 수 있기 때문에 두경우 모두(명시적으로 표현해주던 안해주던) number 타입의 변수에 string 타입의 자료를 넣으면 에러를 리턴한다(타입 체킹을 정상적으로 해준다). 보통 같은 변수에 같은 타입이지만 다른 값을 넣는 경우는 있어도, 갑자기 다른 타입을 넣지는 않기 때문에 이러한 타입체킹은 굉장히 유용하다.
위의 케이스를 보면 나이를 담는 배열(넘버 타입)에 누군가가 이름 정보를(문자열) 넣었다. 하지만, 이 경우에 타입스크립트가 ageInformBox 배열의 타입에 대해서 추론할 수 없기 때문에 이것이 에러라는 것을 알 수 없다. 따라서 컴파일 에러를 일으키지 않는다. 하지만, 실제로 이것이 서비스라고 했을 때 런타임 에러를 일으킨다. 그렇다면 어떻게 해야할까? => 이럴 때 명시적인 타입 표현을 써준다.
위와 같이 number 타입의 요소를 받는 배열이라고 타입을 명확히 표현해주면 아래 push 메서드 단계에서 다음과 같은 컴파일 에러를 리턴한다.
: 위와 같이 타입에대한 명시적 표현은 타입스크립트가 자체적으로 타입추론을 할 수 없는 경우가 아니라면 굳이 써주지 않아도 된다. 그러는편이 코드도 훨씬 짧고, 가독성도 좋기 때문이다.
: 타입스크립트가 엄격하게 타입 체킹 혹은 변수의 개수 등을 검문해주는(?) 것은 알았는데, 너무 엄격해서 예를 들어, 선수(Player)라는 객체를 만들고 거기에 이름, 나이 등의 정보를 담을 때, 나이 정보를 입력하지 않은 선수는 예외적으로 처리하고 싶은 경우에도 에러를 리턴하게 된다. 이러한 상황에서 일부 예외를 허용하기 위해서 Optional Type을 쓰고, 문법은 '?'을 사용한다.
위의 예시는 yongki라는 player를 만드는 예시이다. 이를 보면, Object 타입 내에 키값의 타입을 정해주면서 age: number를 해줬는데, 실제로 할당하는 객체에는 name:'yongki'만 있을뿐 age에 대한 할당을 안해줬다. 그래서 위와 같은 컴파일 에러를 리턴한다. 하지만 이 때 Optional Type을 써주면전혀 시비를 걸지 않는다!. 가끔 서버쪽에서 api response를 보내줄 때 특정한 키값에 값이 없는 경우 아예 해당 키값을 보내지 않을 때도 있는데 그러한 상황에 대비하여 Optional Type을 써도 좋겠다는 생각이 든다.
: Alias는 흔히 들어봤지만, 별칭, 가명과 같은 의미이다. 그러면 type alias는? 위에서 객체를 선언 및 할당할 때 타입을 써줬는데, 예를 들어, 또다른 선수인 TJ를 만들기 위해서는 이런식으로 만들어줘야한다. 하지만 매번 이렇게 해주는 것은 상당히.. 힘들어보인다. 그래서 있는 것이 타입을 일종의 변수처럼 선언해놓고 재사용하는 것이다. 그리고 이를 가능하게 해주는 문법을 type alias라고 생각하면 된다. 위와 같이해주니까 훨씬 코드 가독성도 좋고, 편리하다.
: any는 타입스크립트와 대척점에 있는 타입이다. 달리 표현하면 TS를 쓰는 의미를 퇴색시켜 결국 JS를 쓰는 것과 다름없게 만든다. 그래서 쓰지 않는 것을 권장하지만, 예외적으로 any를 써서 타입스크립트 보고 '타입 시비걸지마!'라고 할 수 있어야하기에 any라는 타입도 존재한다.
위의 상황에서는 any를 쓰는 것이 타입스크립트의 유용성에 반하는 행위(?)라는 것을 보여준다 생각해서 가져와봤다. 위의 상황에서 addPlayer라는 함수를 보면 argument 중에 age를 받을 때 any 타입을 써줬다. 즉, 모든 타입의 변수를 허용한 것이다. 하지만, 뒤에 함수의 return 값에 대한 타입은 Player인데 해당 Alias를 살펴보니 age: number로 정의돼있다. 즉, Player라는 타입 alias는 age를 number로 정의하고 있는데, addPlayer 함수의 리턴 값의 타입이 Player이기에 실제로 addPlayer 리턴값의 age는 number가 돼야맞다. 하지만, argument 중 age를 any로 해놓고 yongki라는 변수에 실제로 addPlayer함수를 통해 하나의 Player 객체를 만들되 age를 "2"로 줬다(문자열로). 그 결과 전혀 문제가 없다는 것을 볼 수 있었고, 그 뒤에 yongki.age = 30으로 다시 number타입의 자료를 할당해줘도 문제가 없음을 볼 수 있었다. 이는 타입스크립트 답지 않은데, 같은 키값인 age에 "2"를 넣어도 문제가 없고, 30을 넣어도 문제가 없는 것 자체가 타입스크립트 답지 않기 때문이다.
위의 코드가 맞는 코드일 것이다(age: number로 변수 타입 설정).
: 갑자기 메모장을 보는듯한 read only? 타입스크립트에서는 특정 변수에 대해서 readonly 속성을 주어 값을 바꾸지 못하게 할 수 있다. 사실 const와 같은게 아닐까? 라고 생각할 수 있지만 array(or tuple)를 생각하면 const보다 더 넓은 기능을 제공한다.
** 이 때, readonly 타입은 객체에는 쓰지 못한다는 점 알아두자
그러면 array 에서 readonly를 쓴 예시를 보자.위의 예시를 보면, VIPS라는 변수에 몇명의 vip 멤버 이름을 string으로만 받도록 했고, 실제로 할당을 해줬다. 그 다음에 VIPS에 'ANONYMOUS USER'를 추가하려고 했더니 에러를 리턴했다. 이렇게 readonly 타입을 지정해주면, 배열에 어떤 값을 추가할 수 없게된다. 말그대로 읽기전용 배열이 되는 것이다. 이런점에서 const보다 좀더 넓은 기능을 갖는데, const로 만든 배열은 재할당이 불가능할뿐 push, pop 등은 가능한데 readonly는 그것이 불가능하다.
위의 예시에서 만들어준 type alias를 튜플 타입이라고 생각하면 된다. 튜플 타입으로 지정해줄 수 있는 것은 배열 요소의 개수, 그리고 그 각 요소의 타입, 그리고 그 각 요소의 타입의 순서이다.
위의 예시를 다시 보면, 먼저, 처음 할당해준
uniqueArr = ['yongki', 30, true];
이부분에서는 문제가 일어나지 않는다.
이 3가지를 모두 충족시켰기 때문이다.
uniqueArr = ['yongki', 30]; // error
하지만 위의 코드는 요소의 개수를 충족시키지 못했기에 에러를 리턴한다.
uniqueArr = [30, [], 'yongki']; // error
그리고 위의 코드는 요소의 개수는 충족시켰지만, 각 요소의 타입 및 순서를 지켜주지 않았다. 사실 아직은 개념적으로만 튜플을 배워서 이걸 어디에 쓸 수 있을까 할 수 있지만, api 통신을 할 때 서버에서 저런 형태의 자료형을 보내는 일이 있을 수 있기에 그러한 상황에서 활용할 수 있을 것 같다.
: 알다시피 undefined & null도 js에 있는 하나의 자료형이다. 그래서 이것또한 타입으로 지정해줄 수 있다. 위에 경우처럼 undefined 타입을 지정해줄 수 있다(null도 마찬가지이다).
아까 Player를 만들면서 배웠던 옵셔널 타입에 마우스 커서를 올려놓으면 age라는 키값의 타입이 number or undefined이라는 것을 볼 수 있다. 그래서 해당 변수에서 age를 안써줘도 자동으로 undefined일 수 있다고 판단하여 에러를 리턴하지 않는 것이다.