3장 타입 추론
타입 추론은 수동으로 명시해야 하는 타입 구문의 수를 엄청나게 줄여 주기 때문에, 코드의 전체적인 안정성이 향상된다. 숙련되면 비교적 적은 수의 타입 구문을 사용할 수 있다.
아이템 19 추론 가능한 타입을 사용해 장황한 코드 방지하기
타입 추론이 된다면 명시적 타입 구문은 필요하지 않다.
- 불필요한 타입 구문을 작성하는 것은 거추장스러울 뿐이다.
정보가 부족해서 타입 스크립트가 스스로 타입을 판단하기 어려운 상황에서 명시적 타입 구문이 필요.
이상적인 타입 스크립트 코드는 함수/메서드 시그니처에 타입 구문을 포함하지만, 함수 내에서 생성된 지역 변수에는 타입 구문을 넣지 않는다.
- 타입 구문을 생략하여 방해되는 것들을 최소화하자.
보통 타입 정보가 있는 라이브러리에서, 콜백 함수의 매개변수 타입은 자동으로 추론해 줌.
// express.Request 타입 생략해도됨..
api.get('/main', (req: express.Request, res: express.Response) => {
res.send('ok');
});
// req, res에 express.Request, Response 타입이 추론되어있음
api.get('/main', (req, res) => {
res.send('ok');
});객체 리터럴을 정의할 때 타입을 명시하면 잉여 속성 체크가 동작해서 유용하다.
함수의 반환에도 타입을 명시하여 오류를 방지할 수 있다.
- 타입 추론이 가능하더라도 구현성의 오류가 함수를 호출한 곳까지 영향을 미치지 않도록 하기 위해 타입 구문을 명시하는 게 좋다.
명명된 타입을 반환하면 좋은 경우
interface Vector2D {
x: number;
y: number;
}
function add(a: Vector2D, b: Vector2D) {
return { x: a.x + b.x, y: a.y + b.y };
}
// 위 코드에서 반환값은 { x : number, y: number } 로 추론된다.
// 사용자 입장에서 Vector2D 타입으로 추론되는게 이해하기 쉬워서 타입을 명시하면 좋음.
아이템 20 다른 타입에는 다른 변수 사용하기
let id = '12-34'; // type : string
id = 123123; // type : number
자바스크립트에서는 동작하는 코드이지만, 타입 스크립트에서는 타입 에러 발생함. (타입 스크립트는 초기화될 때 타입 추론으로 타입을 지정한다)
위 문제는 유니언 타입으로 타입을 확장해서 에러를 피할 수 있다.
- 하지만 id를 사용할 때마다 값이 어떤 타입인지 확인해야 하기 때문에 다루기 더 어렵다.
- 차라리 string, number 각각 별도의 변수를 도입하는 것이 낫다.
별도의 변수를 사용하는 게 바람직한 이유
- 서로 관련 없는 두 개의 값을 분리
- 변수명을 더 구체적으로 지을 수 있음
- 타입 추론을 향상시키며, 타입 구문이 불필요해진다
- 타입이 더 간결해진다
- let 대신 const 변수를 선언하게 된다.
변수의 값은 바뀔 수 있지만, 그 타입은 보통 바뀌지 않는다.
혼돈을 막기 위해 타입이 다른 값을 다룰 때에는 변수를 재사용하지 말자.
아이템 21 타입 넓히기
- 타입 스크립트가 작성된 코드를 체크하는 정적 분석 시점에, 변수는 가능한 값들의 집합인 타입을 가진다.
- 상수를 사용해서 변수를 초기화할 때 타입을 명시하지 않으면 타입 체커는 지정된 단일 값을 가지고 할당 가능한 값들의 집합을 유추해야 한다. 이러한 과정을 '넓히기'라고 부른다.
- 넓히기 과정을 이해한다면 오류의 원인을 파악하고 타입 구문을 더 효과적으로 사용할 수 있다.
interface Vector3 {
x: number;
y: number;
z: number;
}
function getComponent(vector: Vector3, axis: 'x' | 'y' | 'z') {
return vector[axis];
}
let x = 'x';
let vec: Vector3 = { x: 10, y: 10, z: 10 };
// ERR : 'string' 형식의 인수는 '"x" | "y" | "z"' 형식의 매개 변수에 할당될 수 없습니다.
getComponent(vec, x);
위의 코드에서 x는 string으로 추론되기 때문에 에러가 발생한다.
타입 스크립트는 타입을 추론할 때 명확성과 유연성 사이의 균형을 유지하려고 한다.
- 추측한 답이 항상 옳을 수는 없다.
let 대신 const로 변수를 선언하면 더 좁은 타입이 된다.
const y = 'y'; // type : 'y'- 하지만 const는 만능이 아니다. 객체나 배열의 경우에 여전히 문제가 있다.
타입 추론의 강도를 직접 제어하려면 타입 스크립트의 기본동작을 재정의해야 한다.
- 명시적 타입 구문 제공
- 타입 체커에 추가적인 문맥 제공
- as const 단 언문 사용
- let const와 다르다. 온전히 타입 공간의 기법
- 값 뒤에 as const를 작성하면, 타입 스크립트는 최대한 좁은 타입으로 추론한다.