이펙티브 타입스크립트 (댄 밴더캄 지음) 를 읽고 정리
더보기
5장 any 다루기
#38 any 타입은 가능한 좁은 범위에서만 사용하기
📍요약
✅any 의 사용 범위를 최소한으로 좁혀야 한다
✅함수의 반환 타입이 any이면 절대 안된다 -> 다른 코드에 악영향을 미침
✅강제로 타입 에러를 제거하려면 any 대신 @ts-ignore가 낫다
📍함수의 매개변수로 any 사용할 때
- 함수의 매개변수로 any를 사용해야 할 때는
매개변수 as any 형태로 사용하여 다른 코드에 영향이 없도록 하는 것이 좋다
interface Foo { foo: string; }
interface Bar { bar: string; }
declare function expressionReturningFoo(): Foo;
function processBar(b: Bar) { /* ... */ }
function f() {
const x = expressionReturningFoo();
processBar(x);
// ~ Argument of type 'Foo' is not assignable to
// parameter of type 'Bar'
}
// bad case
function f1() {
const x: any = expressionReturningFoo();
processBar(x);
// return x;
// 함수 호출 후에도 x의 타입이 any
}
// 차라리 이렇게 사용
// any 타입이 다른 코드에 영향을 미치지 않음
function f2() {
const x = expressionReturningFoo();
processBar(x as any); // 일시적으로 any
// 함수 호출 후에는 x의 타입이 Bar
}
만약, f1 함수가 x 를 리턴한다면 문제가 더 커진다
- 반환값의 타입이 Bar 에서 any 로 바뀌어, 다른 코드에 영향을 미칠 수 있다
@ts-ignore 를 사용해서 문제를 일시적으로 해결할 수도 있다
interface Foo { foo: string; }
interface Bar { bar: string; }
declare function expressionReturningFoo(): Foo;
function processBar(b: Bar) { /* ... */ }
function f1() {
const x = expressionReturningFoo();
// @ts-ignore : 다음줄의 타입 에러를 무시
processBar(x); // x 타입이 Foo 이지만 타입에러 없음
return x;
}
📍객체의 필드에서 any를 사용할 때
객체 전체를 단언하면 다른 프로퍼티들의 타입 체크 기능이 무력화된다
- 따라서 최소한의 범위에서만 any를 사용하는 것이 좋다
interface Foo { foo: string; }
interface Bar { bar: string; }
declare function expressionReturningFoo(): Foo;
function processBar(b: Bar) { /* ... */ }
interface Config {
a: number;
b: number;
c: {
key: Foo;
};
}
declare const value: Bar;
const config: Config = {
a: 1,
b: 2,
c: {
key: value // key 프로퍼티는 Foo 타입인데, value가 Bar 타입이라 에러 발생
}
};
// bad case
const config1: Config = {
a: 1,
b: 2,
c: {
key: value
}
} as any; // 다른 프로퍼티 a, b 의 타입 체크도 무력화됨
// 차라리 이렇게
const config2: Config = {
a: 1,
b: 2,
c: {
key: value as any
}
};