-
타입스크립트는 타입 추론을 적극적으로 수행한다.
-
타입 추론은 수동으로 명시해야 하는 타입 구문의 수를 엄청나게 줄여준다. -> 코드의 전체적인 안정성 향상.
-
타입스크립트 초보자 vs 숙련자 -> 타입 구문의 수에서 차이 보임.
-
전부 다 타입을 도배할 필요가 없다는 것을 알 수 있음. 불필요한 타입 구문은 필요없음.
-
타입 추론에서 발생할 수 있는 문제와 그 해법이 3장의 내용.
-
목표: 타입 추론이 가능한 경우라도 타입 선언을 작성해야 하는 것이 필요한 상황은 언제인지 이해하기.
아이템 19 추론 가능한 타입을 사용해 장황한 코드 방지하기
- 결국 타입을 위한 언어 -> 변수를 선언할 때마다 타입을 명시해야 한다고 생각 -> 정곡
- let x: number = 12; (x) -> let x = 12; 로 충분. 마우스를 올려보면 number로 이미 추론되어 있음.
- 편집기의 타입 추론을 잘 활용하는 것이 초보자에게 중요할 것으로 보임.
- 타입 추론이 되면 명시적 타입 구문은 필요하지 않음. 오히려 방해가 됨.
- 타입 확신 못한다면 편집기를 통해 체크.
- 보통 타입 정보가 있는 라이브러리에서 콜백 함수의 매개변수 타입은 자동으로 추론됨.
- express HTTP의 서버 라이브러리를 사용하는 request, response의 타입 선언은 필요없음.
- 추론 될 수 있는 경우여도 객체 리터럴, 함수 반환형 등은 타입 명시를 고려하는 것이 필요함.
- 아래 소스에서 add에 마우스를 올려보면 반환형도 x: number, y: number이라고 나옴.
interface Vector2d {
x: number;
y: number;
}
function add (a: Vector2d, b: Vector2d) {
return {
x: a.x + b.x,
y: a.y + b.y
}
}
const test: Vector2d = {x: 1, y: 2};
const test2: Vector2d = {x: 1, y: 2};
add(test, test2);
아이템 20 다른 타입에는 다른 변수 사용하기
- 변수의 값은 바뀔 수 있지만 그 타입은 보통 바뀌지 않는다.
- ex.) let id = "001";
- id = 1; (x)
- ~~ '1' 형식은 'string' 형식에 할당할 수 없습니다.
- 타입을 바꿀 수 있는 방법은 범위를 좁히는 것. 새로운 변수값 포함하도록 확장이 아닌, 타입을 더 작게 제한.
- id의 타입을 바꾸지 않고 둘 다 사용하는 방법은 타입을 확장하는것.
- let id: string | number = "001";
- 어찌보면 당연한 이야기. 혼란을 발생하는 경우를 방지하라는 것이 포인트.
아이템 21 타입 넓히기(현재 내가 타입을 사용하는데 있어서 중요할 것 같음)
- 런타임에 모든 변수는 유일한 값을 가짐.
- 그러나 타입스크립트가 작성된 코드를 체크하는 정적 분석 시점에는 아님.
- 변수는 타입을 가짐. (타입 = 가능한 값들)
- 상수를 사용해서 변수를 초기화 할 때 타입을 명시하지 않으면, 타입 체커는 타입을 결정해야 함.
- 즉, 타입 명시 x -> 할당된 값을 갖고, 타입 체커가 타입을 유추.
- 타입스크립트에서는 이러한 과정을 widening(넓히기) 라고 함.
- 이 과정을 이해하는 것을 통해 오류의 원인을 파악하고 타입 구문을 더욱 효과적으로 사용할 수 있음.
- 아래와 같은 코드는 런타임에서는 문제가 발생하지 않지만, 편집기에서 에러가 발생함.
- getComponent(test, x);에서 두 번째 매개변수에 "x" | "y" | "z"를 기대했지만, x의 타입은 할당 시점에 widening이 동작해서 string으로 추론되었기 때문임.
interface wideningTest {
x: number,
y: number,
z: number,
}
function getComponent(test: wideningTest, stringType: 'x' | 'y' | 'z') {
return test[stringType];
}
let x = 'x';
let test = { x: 10, y: 20, z: 30};
getComponent(test, x);
- widening이 진행될 때, 주어진 값으로 추론 가능한 타입은 여러 개임. 그래서 해당 과정이 모호함.
- 아래와 같은 타입은 의도한 것과 마찬가지로 number | string의 타입으로 타입 체커가 추측함.
- 하지만 모든 타입을 타입체커가 작성자의 의도에 맞게 추측할 수 없음.
- 즉, 어떤 코드들이 mixed타입들이 되는지 알고 있어야 타입 체커를 의도한대로 사용할 수 있음.
const mixedType = [1, "x"];
- 아래 코드들이 mixed 타입이 될 수 있는 타입들임.
('x' | 1)[]
['x', 1]
[string, number]
readonly [string, number]
(string|number)[]
readonly (string|number)[]
[any, any]
any[]
const test = {
x: 1,
y: 2
}
const test2 = {
x: 1 as const,
y: 2
}
const test3 = {
x: 1,
y: 2
} as const
- 위 코드의 주석들은 편집기에서 마우스를 올려 타입 추론된 결과를 복사한 것.
- as const는 타입스크립트가 최대한 좁은 타입으로 추론할 수 있게 해줌.
- test3에는 넓히기가 동작하지 않았음.
아이템 22 타입 좁히기(?)
- 타입 넓히기 widening의 반대.
- 타입스크립트가 넓은 타입으로부터 좁은 타입으로 진행하는 과정을 말함.
- 일반적인 예시는 null체크
아이템 23 한꺼번에 객체 생성하기
- 타입스크립트의 타입은 일반적으로 변경되지 않는다(아이템 20참조)
- 이 특성으로 일부 자바스크립트 패턴을 타입스크립트로 모델링 하는 것이 쉬워진다. (?)
- 객체를 생성할 때 속성 하나씩 추가 X
- 여러 속성을 포함해 한 번에 생성해야 타입 추론에 유리
const pt = {};
pt.x = 3;
pt.y = 3;
interface Point { x: number, y: number; }
const pt2: Point = {};
const pt3 = {} as Point;
pt3.x = 3;
pt3.y = 3;
- 위와 같이 객체를 반드시 제각각 나눠서 만들어야 한다면 타입 단언문을 사용해 타입 체커를 통과할 수 있음.
- 작은 객체를 조합해서 큰 객체를 만들어야 하는 경우도 Object.assign ~ 을 사용해서 여러 단계를 거치는 것은 좋지 않음.
const pointer = {x: 3, y: 4};
const id = {name: 'fullth'}
const namePoint = {...pointer, ...id};
namePoint.name
- 객체 전개 연산자 ... 를 사용하면 됨.
- 타입 걱정 없이 필드 단위로 객체를 생성할 수 있음.
- 조건부로 속성을 추가할 수 있음.
- 필요하지 않은 속성은 제외가능