TypeScript(TS)는 기본적으로 Javascript complier다.
TS는 Strongly type 언어이고 JS에서 발생할 수 있는 오류를 미리 감지하고 경고해준다. 따라서 TS에서 오류가 없다면 JS에서도 오류가 없을 것이다. 이것은 마치 모래를 촘촘한 거름망을 통해 먼저 걸러내는 것과 비슷하다. 촘촘한 거름망으로 걸러내고 나면 더 큰 거름망에서는 아무런 문제 없이 통과할 것.
TS는 암묵적 Type과 명시적 Type을 모두 지원한다.
Type은 변수를 선언할 때 명시적으로 지정해줘야한다. 그렇지 않으면, 변수 선언 후 처음으로 할당될 때를 기준으로 Type이 추론된다. 따라서 처음 할당된 변수의 Type과 다른 Type을 추후에 섞어서 쓰게 되면 에러가 뜬다.
변수의 Type은 기본적으로 콜론(:) 뒤에 기재하는 방식을 통해 명시적으로 지정할 수 있다.
즉, <변수 선언 키워드> <변수명> : <Type> 순으로 기재한다.
const car : string
위와 같이 선언된 변수 car는 string이 아닌 다른 Type을 가질 수 없다.
TS는 JS의 리터럴 표현을 지원하기 때문에, 만약 숫자로 이루어진 Array를 정의하고 싶다면 number[ ] 와 같이 배열 리터럴을 통해 표현 가능하다.
혹은 Array<number> 의 형태로 우직하게 표현하는 것도 가능하다. 이런 형태의 표현은 Array, Object, Class 등에 쓰일 수 있다.(자료구조를 구성하고 있는 내부의 요소값의 속성을 <>안에 적어준다.)
또한, 객체의 프로퍼티 키로 어떤 것이 올지 모르는 경우에는 아래와 같이 타입만 지정하고 넘어가는 것도 가능하다.
key 자리에는 당연히 아무 단어가 와도 무방하다.
type ObjectSetting = {
[key:string] : string
}
다만, 리터럴을 통해 표기 하면 가독성이 떨어지는 경우가 있는데, 이럴 때 type 명령어를 통해 나만의 Type을 생성한 뒤 이를 활용하여 축약적으로 Type을 지정해 줄 수 있다(Alias)
두 개를 잘 비교해보면 알겠지만, 아래의 type Car에 할당된 우변의 코드를 const car : Car 의 Car 자리에 대입하면 위와 아래는 완전히 동일한 코드가 된다.
다시 말해, 위 예제에서 type 을 통해 생성된 Car는 그냥 Type에 관한 정보를 담고 있는, 오직 TS에서만 쓰이는 변수의 일종에 지나지 않는다는 의미이다. 즉, TS에서 type 키워드는 JS에서 const, let, var 키워드와 똑같은 기능을 수행한다.
그리고 내가 생각했을 때 이 내용이야말로 TS에서 가장 중요한 개념적 인식이다. 이 개념이 안 잡혀 있으면 나중에 헷갈리기 쉽고, 이 개념만 꽉 잡고 있으면 TS는 어려울게 없다.
Call Signature란, Function에 대한 Alias를 말한다.
Call Signature는 근본적으로 변수에 대한 Alias 설정과 다를 바 없다. 다만, Alias와 달리 변수가 아니라 함수, 정확히는 함수의 인자와 반환값에 대한 Type을 설정해주는 것을 말한다.
하지만, 함수의 인자와 반환값에 대해 Type을 설정하든, 그냥 변수에 대해 Type을 설정하든 Type에 관한 설정값을 한 단어에 할당한다는 점에서 type 키워드를 통한 Alias(별명!) 설정과 동일한 메커니즘을 지닌다.
type <Type Alias 이름> = {
(<argument name> : <argument Type>) : <retrun Type>
}
Overloading이란, 두 개 이상의 Call Signature가 있을 때를 말한다.
하나의 함수가 여러가지 조합의 인수를 받을 수 있는 경우 활용된다. 예를 들어 어떤 함수에서 Boolean Type을 받아와야하는 경우에 있어서, 혹시라도 값이 String으로 전달되는 경우에도 이를 핸들링하고 싶을 때 쓸 수 있다.
type TakeBoolean = {
(a : boolean) : string
(a : string) : string
}
const sayBoolean : TakeBoolean = (a) => {
if (typeof a === "boolean"){
return `It is ${a}`
} else if (a === 'true' || a === 'True'){
return `It is true`
} else if (a === 'false' || a === 'False'){
return `It is false`
} else {
return `Argument type must be Boolean.`
}
}
Polymorphism(다형성)은 이름에서 알 수 있듯, 여러 타입으로 폴리모프(!)할 수 있는 성질을 말하는데, 다형성을 지닌 Type을 가리켜 Generic이라고 부른다.
암묵적 타입추론을 명시적으로 표기한다고 이해해도 무방하다. 즉, 명시적 타입추론을 구현한 개념이 Generic이다.
그렇다면 왜 암묵적 타입추론이 있음에도 명시적 타입추론이 필요할까?
첫 번째 이유는 하나의 값에 여러 Type이 올 수 있을 때, 이를 일일이 지정해주기 귀찮고 불편하며 경우에 따라, 사실상 불가능에 가까운 막노동이 될 수도 있다는 점이고,
두 번째 이유는 암묵적 타입 추론과 달리 명시적으로 추론의 대상이 되는 코드를 지정해줄 수 있기 때문에 보다 더 편리하고 안전하기 때문이다.
type ReturnArray = <T>(arr:T[]) => T[]
위 코드에서 <T> 부분은 Generic으로서 T라는 다형적 Type을 쓴다라는 의미이다. 즉, <>안에는 아무 단어가 와도 좋다. 다만, 일반적으로 T를 쓰는 것이 관행이다.(Type의 약자)
이처럼 <T>를 써서 Generic의 존재를 알리고 나면, 어디에서 T라는 다형적 Type을 추론해야하는지 알려줘야 하는데, 이것이 바로 ( arr: T[ ] )의 T[ ]부분이다.
위에서 이미, TS에서 리터럴을 지원한다는 것을 말한적 있다. T[ ] 역시 리터럴 표현일 뿐이다. 다시 말해, T라는 타입으로 구성된 Array 라는 의미이다. 따라서, 해당 Array 안에 오는 모든 요소의 타입으로부터 T라는 다형적 Type은 추론된다.
또한, Array<T>와 같은 문법도 당연히 지원한다. Generic은 명시적 추론을 의미하는 다형적 Type일 뿐이므로 Type을 쓸 수 있는 곳에는 어디든 쓸 수 있다. (Array<T>와 T[ ]는 근본적으로 같은 의미이다)
Generic에 대해 더 자세한 내용은 아래 포스팅을 참고
TS에서는 몇가지 재미난 Type 및 옵션이 제공된다.
- 변수명 뒤에 ?를 붙이면 있을 수도 없을 수도 있는 선택적 항목(optional)으로 처리된다. 반대로 말해서 ?가 없다면 그 항목은 required 이다.
더 중요한 점은, 예를 들어 객체에서 ?를 통해 '가능성이 있는 프로퍼티'를 선언해두지 않는다면, 추후 프로퍼티를 추가할 수 없다. 어떤 의미에서는 당연하기도 하다. TS입장에서 해당 객체는 객체 선언 당시 정해진 프로퍼티만을 가지는 객체이기 때문이다. - readonly를 붙이면 읽기전용으로 처리된다. immutability 속성을 추가하는 셈.
- any 타입은 TS의 적용제외를 명령하는 것과 다를 바 없다.
- never 타입은 어떤 값을 가져서는 안되는 변수에 쓰인다. 조건문 등에서 자주 쓰인다.
- unknown 타입은 변수의 타입을 먼저 확인하기 전까지 코드의 진행을 멈추는 역할을 한다. 따라서 if 등을 통해 Type에 따른 분기점을 형성해줘야만 한다.
- void 타입은 return 하지 않는 변수에 쓰인다. return 과 관련하여 아무 타입도 명시하지 않는다면 기본값으로 설정된다.
- 어떤 값의 Type(자료형) 뿐만 아니라 자료 그 자체의 값과 개수를 명시적으로 규정할 수도 있다. 이를 활용하면 JS에는 없는 Tuple 같은 자료구조도 구현할 수도 있다.
type Customer = {
name : string,
gender : '남자' | '여자' | '비공개'
size : ['XS' | 'S' | 'M' | 'L' | 'XL' | 'XXL', number, number]
}
위와 같이 작성하면, gender에는 반드시 '남자', '여자', '비공개' 셋 중에 하나의 값만 올 수 있고,
size의 경우에는 순서대로 string, number, number가 올 수 있는 Array로 설정되며, 특히 string의 경우 'XS', 'S', 'M', 'L', 'XL', 'XXL' 중 하나의 값만 올 수 있게 된다.
'Learning-Log > Computer Science' 카테고리의 다른 글
Tistory의 코드블럭을 이쁘게 만들어보자 : 코드블럭 테마 (highlight.js) 적용방법 (0) | 2022.07.06 |
---|---|
[TS] 타입스크립트의 기초(2) - Class와 상속, 그리고 interface와 type의 차이점 (0) | 2022.07.05 |
[TS] 타입스크립트 Generic에 대한 이해와 활용 (0) | 2022.07.01 |
[NPM] 패키지 설치시 더 이상 '--save' 플래그를 입력하지 않아도 되는 이유 (0) | 2022.06.24 |
[JS] 자바스크립트의 배열(Array)은 배열이 아니다. (0) | 2022.06.19 |