
→ 자바스크립트 프로그램에 문법 오류가 없다면, 유효한 타입스크립트 프로그램이다.
→ 자바스크립트 프로그램에 이슈가 존재한다면 문법 오류가 아니더라도 타입 체커에서 지적당할 가능성이 높다.
→ 문법의 유효성과 동작의 이슈는 독립적인 문제

모든 자바스크립트는 타입스크립트이지만, 모든 타입스크립트가 자바스크립트는 아니다!
.js파일에 있는 코드는 이미 타입스크립트라고 할 수 있기 때문에 JS -> TS로 마이그레이션하는 데 엄청난 이점이 된다.
→ 그러나 타입 체커가 모든 오류를 찾아내지는 않음
→ 타입 체커를 통과하면서 런타임 오류를 발생시키는 코드는 충분히 존재.
const x = 2 + '3' // 정상 string 타입
const y = 2 + '3' // 정상 string 타입
위 예제가 다른 언어였다면 런타임 오류가 될 만한 코드지만 타입 체커는 정상으로 인식한다.
const name = ['Alice', 'Bob'];
console.log(name[2].toUpperCase()); // TypeError : Cannot read property 'toUpperCase' of undefined
타입스크립트는 앞의 배열이 범위 내에서 사용될 것이라고 가정했지만 실제로는 범위를 벗어나서 런타임 오류가 발생했다.
타입스크립트가 이해하는 값의 타입과 실제 값에 차이가 존재하기 때문에 발생하는 오류들이다. 타입 시스템이 정적 타입의 정확성을 보장해줄 것 같지만 그렇지 않기 때문이다.
tsconfig.json을 사용하자!strict: true 설정을 고려하자.TS/JS를 브라우저에서 동작할 수 있도록 구버전의 자바스크립트로 트랜스파일(transpile) 한다.이 두가지는 서로 완벽히 독립적이다.
- 타입스크립트가 자바스크립트로 변환될 때 코드 내의 타입에는 영향을 주지 못한다.
- 자바스크립트의 실행 시점에서 타입은 영향을 미치지 않는다.
오류가 있을 때 컴파일 X -> tsconfig.json에 noEmitOnError를 설정
인터페이스,타입,타입 구문은 제거되어 버린다.타입은
런타임 이전, 값은런타임 때
interface Square {
width: number;
}
interface Rectangle extends Square {
height: number;
}
type Shape = Square | Rectangle;
function calculateArea(shape: Shape){
// Rectangle은 형식만 참조하지만, 여기서 값으로 사용되고 있습니다.
if(shape instanceof Rectangle) {
// Shape 형식에 height가 없습니다.
return shape.width * shape.height;
} else {
return shape.width * shape.width;
}
}
위 코드에서 shape의 타입을 명확하게 하려면 런타임에 타입 정보를 유지하는 방법이 필요하다. 다음 3가지 방법으로 런타임때 타입 정보를 유지할 수 있다.
1. 속성이 존재하는지 체크
function calculateArea(shape: Shape){
if('height' in shape) { // 타입이 Rectangle
return shape.width * shape.height;
} else { // 타입이 Square
return shape.width * shape.width;
}
}
2. 런타임에 접근 가능한 타입 정보를 명시적으로 저장하는 태그기법(tagged union)
interface Square {
kind: 'square'; // tagged union
width: number;
}
interface Rectangle {
kind: 'rectangle';
width: number;
height: number;
}
type Shape = Square | Rectangle;
function calculateArea(shape: Shape){
if(shape.kind === 'rectangle') { // 타입이 Rectangle
return shape.width * shape.height;
}
// ...
}
런타임에 타입 정보를 손쉽게 유지할 수 있어 흔하게 볼 수 있다.
3. class로 만들기
인터페이스는 타입으로만 사용 가능,클래스로 선언하면 타입과 값으로 모두 사용할 수 있으므로 오류가 없다.
function adNumber(val: number | string): number {
return val as number; // number 타입으로 단언한다.
}
function asNumber(val){
return val;
}
타입스크립트에서 런타임 타입과 선언된 타입이 맞지 않을 수 있기 때문에, 언제든 선언된 타입이 달라질 수 있다는 것을 명심해야한다.
타입스크립트에서 타입과 런타임의 동작은 무관하기 때문에 함수 오버로딩 기능을 지원하긴 하지만 온전히 타입 수준에서만 동작한다. 하나의 함수에
여러 개의 선언문은 가능,구현체는 오직 하나뿐이다.
📌 핵심
자바스크립트는 본질적으로 덕 타이핑(duck typing) 기반이다. 만약 어떤 함수의 매개변수 값이 모두 제대로 주어진다면, 그 값이 어떻게 만들어 졌는지 신경쓰지 않고 사용한다.
덕 타이핑이란, 객체가 어떤 타입에 부합하는 변수와 메서드를 가질 경우 객체를 해당 타입에 속하는 것으로 간주하는 방식이다.
interface Vector2D {
x: number;
y: number;
}
// 벡터의 길이를 구하는 함수 (2D)
function calculateLength(v: Vector2D) {
return Math.sqrt(v.x * v.x + v.y * v.y);
}
interface Vector3D {
x: number;
y: number;
z: number;
}
// 3D 벡터의 길이를 1로 만드는 정규화 함수
function normalize(v: Vector3D) {
const length = calculateLength(v);
return {
x: v.x / length,
y: v.y / length,
z: v.z / length,
};
}
// 함수 normalize는 1보다 조금 더 긴 길이를 가진 결과를 출력
normalize({x: 3, y: 4, z: 5})
// {x: 0.6, y: 0.8, z: 1}
타입스크립트는 오류를 잡지 못했다. 그 이유는 calculateLength는 2D 벡터를 기반으로 연산하는데, 버그로 인해 normalize가 3D 벡터로 연산되었기 때문이다. z가 정규화 과정에서 무시되었다. 타입 체커는 이 문제를 잡아내지 못했다.
이 원인을 조금 더 살펴보면, Vector3D와 호환되는 {x, y, z} 객체로 calculateLength를 호출하면, 구조적 타이핑 관점에서 x, y가 있어서 Vector2D와 호환된다. 따라서 오류가 발생하지 않았고, 타입 체커가 문제로 인식하지 않았다.
함수를 작성할 때, 호출에 사용되는 매개변수의 속성들이 타입에 선언된 속성만을 가질거라 생각하기 쉽지만(
봉인된(sealed), 정확한(pricise)타입) 타입스크립트의 타입 시스템은 항상열려(open)있다.
구조적 타이핑이란?
- 구조적 타이핑은 타입의 구조가 일치하는지 여부를 기준으로 타입을 비교하고 호환성을 결정하는 방식
// 구조적 타이핑을 가정하는 가상의 언어 예제 type Person = { name: string; age: number; }; const person1: Person = { name: "Alice", age: 30 }; const person2: Person = { name: "Bob", age: 25 }; // person1과 person2는 같은 타입으로 간주
일부 특별한 경우를 제외하고 any를 사용하게 되면 타입스크립트의 수많은 장점을 누릴 수 없게 된다.
1. any 타입에는 타입 안전성이 없다.
age += 1; //"121"
2. 함수 시그니처를 무시한다.
약속된 타입의 입력 제공, 함수는 약속된 타입의 출력을 반환해야 한다. 그러나 any를 사용하면 이러한 약속을 어길 수 있다.3. 언어 서비스가 제공되지 않는다.
4. 코드 리팩토링 때 버그를 감춘다.
5. 타입 설계를 감춘다.
6. 타입 시스템의 신뢰도를 떨어뜨린다.
any 타입을 사용하면
타입 체커와타입스크립트 언어 서비스를 무력화시켜 버린다. 진짜 문제점을 감추며 타입 시스템의 신뢰도를 떨어뜨리기 때문에 최대한 사용을 피하도록 하자!!