-타입스크립트는 자바스크립트의 상위집합이다.
모든 자바스크립트 프로그램은 이미 타입스크립트 프로그램이다.
타입스크립트는 별도의 문법을 가지고 있기 때문에 일반적으로는 유효한
자바스크립트 프로그램이 아니다.
자바스크립트 파일이 js(또는 .jsx)확장자를 사용하는 반면
타입스크립트 파일은 ts(또는 .tsx) 확장자를 사용한다.
모든 자바스크립트는 타입스크립트이지만, 모든 타입스크립트가 자바스크립트는 아니다.
ts
function greet(who: string) {
console.log('Hello', who);
}
js
function greet(who: string) {
^
SyntaxError: Unexpected token :
string은 타입스크립트에서 쓰이는 타입구문이다.
따라서 js에서 사용하게 되면 문법 오류가 난다.
js
let city = 'new york city';
console.log(city.toUppercase());
TypeError: city.toUppercase is not a function;
ts
let city = 'new york city';
console.log(city.toUppercase());
// ~~~~~~~~~~~~'toUppercase' 속성이 'string' 형식에 없습니다.
// 'toUpperCase'를 사용하시겠습니까?
이와같이 앞 js 코드에는 타입 구문이 없지만, ts의 타입 체커는 문제점을 찾아 낸다. -city 변수가 문자열이라는 것을 알려 주지 않아도 타입스크립트는 초깃값으로 부터 타입을 추론한다.
-타입 시스템의 목표중 하나가 런타임에 오류를 발생시킬 코드를 미리 찾아내는 것이기 때문에 이로써 타입스크립트는 정적타입 시스템이라 할 수 있다.
그러나 타입 체커가 모든 오류를 찾아내지는 않는다 오류가 발생하지는 않지만 의도와 다르게 동작하는 코드도 있다.
const x = 2 + '3'; // 정상, string 타입입니다.
const y = '2' + 3; // 정상, string 타입입니다.
위 예제는 다른 언어였다면 런타임 오류가 뜨는 코드이지만, 타입스크립트의 타입 체커는 정상으로 인식한다 두 줄 모두 문자열"23"이 되는 자바스크립트 런타임 동작으로 모델링 되는데 반대로 정상 동작하는 코드에 오류를 표시하기도 한다.
😥정상 동작하는 코드에 오류 표시하는 경우
const a = null + 7; // 자바스크립트에서는 a값이 7이 됩니다.
// ~~~ '+' 연산자를 ... 형식에 적용할 수 없습니다.
const b = [] + 12; // 자바스크립트에서는 b값이 '12'가 됩니다.
// ~~~~~~~ '+' 연산자를 ... 형식에 적용할 수 없습니다.
alert('Hello', 'TypeScript'); // "Hello" 경고를 표시합니다.
// ~~~~~~~~~~~~~ 0-1개의 인수가 필요한데 2개를 가져왔습니다.
타입스크립트는 어떻게 설정하느냐에 따라 완전히 다른 언어처럼 느껴 질 수 있는데 noImplicitAny 와 strictNullChecks 를 이해해야 한다.
noImplicitAny는 변수들이 미리 정의된 타입을 가져야하는지 여부를 제어한다는 설정인데 "암시적 any가 금지된다" 는 설정이다 타입스크립트는 타입 정보를 가질 때 가장 효과적이기 때문에 이 옵션은 되도록 설정하도록 권장되어 진다.
자바스크립트 프로젝트를 타입스크립트로 마이그레이션 하는 경우가 아니라면 noImplicitAny를 설정하는 것이 좋다.
새 프로젝트를 시작한다면 처음부터 noImplicitAny를 설정하여 코드를 작성 할 때마다 타입을 명시하도록 해야 한다.
->타입스크립트가 문제를 발견하기 수월해지고, 코드의 가독성이 좋아지며, 개발자의 생산성이 향상된다.
strictNullChecks는 null과 undefined가 모든 타입에서 허용되는지 확인하는 설정이다. null, undefined 관련된 오류를 잡아 내는 데 많은 도움이 되지만, 코드 작성이 어려워진다 새 프로젝트라면 설정하는게 좋지만 마이그레이션하는 프로젝트라면 힘들어 질 수 있다.
새 프로젝트를 시작한다면 가급적 strictNullChecks를 설정하는 것이 좋지만, 타입스크립트가 처음이거나 자바스크립트 코드를 마이그레이션하는 중이라면 설정하지 않아도 괜찮다.
strictNullChecks를 설정하려면 noImplicitAny를 먼전 설정해야 한다.
- 최신 ts, js를 브라우저에서 동작할 수 있도록 구버전의 자바스크립트로 *트랜스 파일(transfile)한다.
- 코드의 타입 오류를 체크한다.
다시말해 타입스크립트가 자바스크립트로 변활될 때 코드 내의 타입에는 영향을 주지 않는다. 또한 그 자바스크립트의 실행 시점에도 타입은 영향을 미치지 않는다
let x = "hello";
x = 1234;
// ~ number 형식은 string에 할당될 수 업습니다.
// tsc test.ts ->
// test.js
let x = "hello";
x = 1234;
interface Car {
name: string;
}
interface Truck extends Car {
weight: number;
}
type Vehicle = Car | Truck;
function foo(ele: Vehicle) {
if (ele instanceof Truck) {
return ele.weight;
} else {
return ele.weight;
}
}
instanceof는 결국 ele 가 Truck이라는 생성자에 해당 값이 존재하는지를 판별하는 것인데
Truck은 오로지 type의 역활만을 하고 type은 런타임환경에서는 제거된 상태이다.
그렇기 때문에 런타임환경에서는 아무역활을 하지 못한다.
string 또는 nuber 타입인 값을 항상 number로 정제하는 경우를 가정해 보면 다음 코드는 타입 체커를 통과하지만 잘못된 방법을 사용하였다.
function asNumber(val: number | string): number {
return val as number;
}
이 코드는 다음 js코드로 변환된다.
function asNumber(val) {
return val;
}
코드에 아무런 정돈한 과정이 없다. as number는 타입 연산이고 런타임 동작에는 아무런 영향을 미치지 않는데 값을 정제하기 위해서는 런타임의 타입을 체크하고 자바스크립트 연산을 통해 변환을 수행해야 한다.🔽
function asNumber(val: number | string): number {
return typeof(val) === 'string' ? Number(val) : val;
}
function setLightSwitch(value: boolean) {
switch (value) {
case true:
turnLightOn();
break;
case false:
turnLightOff();
break;
default:
console.log(`I'm afraid I can't do that.`);
}
}
위 함수를 보고 마지막 consol.log문이 실행되나 생각해보면
타입스크립트는 일반적으로 실행되지 못하는 dead코드를 찾아 내지만 위 코드에서는 찾아내지 못한다.
위 마지막 consol.log문을 실행할려면 어떻게 해야할까
=> 위 코드의 value: boolean에서 : boolean은 타입 선언문이다. 만약 value가 문자열이라면 default 케이스가 실행될 수 있다.
타입 체킹을 했으므로 그럴 일은 일어날 수 없다 생각할 수 있겠지만 네트워크 호출로부터 받아온 값으로 함수를 실행하는 경우 데이터가 문자열일 수 있다.
타입스크립트에서는 런타임 타입과 선언된 타입이 맞지 않을 수 있습니다.
ts는 타입과 런타임의 동작이 무관하기 때문에 함수 오버로딩은 불가능하다.
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a, b) {
return a + b;
}
ts가 함수 오버로딩 기능을 지원하기는 하지만, 온전히 타입 수준에서만 동작한다
위 코드에서는 add에 대한 처음 두 개의 선언문은 타입 정보를 제공할 뿐 이 두선언문은 타입스크립트가 자바스크립트로 변환되면서 제거되며, 구현체만 남게 된다.
타입과 타입 연산자는 자바스크립트 변환 시점에 제거되기 때문에 런타임의 성능에 아무런 영향을 주지 않는다.
타입스크립트의 정적 타입은 실제로 비용이 전혀 들지 않는다.
다만, 빌드타임 오버헤드는 있다.