[이펙티브 타입스크립트] 아이템38 ~ 아이템40

Yongwoo Cho·2022년 6월 8일
0

TIL

목록 보기
85/98
post-thumbnail

[아이템38] any 타입은 가능한 좁은 범위에서만 사용하기

function processBar(b: Bar) {
  /* ... */
}
function f() {
  const x = expressionReturningFoo();
  processBar(x); // ❌ 'Foo' 형식의 인수는 'Bar' 형식의 매개변수에 할당될 수 없다
}

✔️ 오류 제거 방법

// 1
function f1() {
  const x: any = expressionReturningFoo();
  processBar(x);
}
// 2
function f2() {
  const x = expressionReturningFoo();
  processBar(x as any);
}

f2형식으로 작성하는 것이 더 권장됨.

❓ 이유는?

👉 any 타입이 processBar 함수의 매개변수에서만 사용된 표현식이므로 다른 코드에는 영향을 미치지 않기 때문이다. f1에서는 마지막까지 x의 타입이 any이다.

큰 객체 안의 한 개 속성이 타입 오류를 가지는 상황

const config: Config = {
  a: 1,
  b: {
    key: value, // ❌ 'foo'속성이 'Foo'타입에 필요하지만 'Bar'타입에는 없습니다.
  },
};

const correctConfig: Config = {
  a: 1,
  b: {
    key: value as any,
  },
};

❕ 강제로 타입 오류를 제거하려면 any 대신 @ts-ignore을 사용하자

[아이템39] any를 구체적으로 변형해서 사용하기

❗ any 타입의 값을 그대로 정규식이나 함수에 넣지 말자

function getLengthBad(array: any) {
  return array.length;
}
function getLength(array: any[]) {
  return array.length;
}

👍 getLength 함수가 좋은 이유

  • 함수 내의 array.length 타입이 체크됨
  • 함수의 반환 타입이 any 대신 number로 추론됨
  • 함수 호출 시 매개변수가 배열인지 체크됨

함수의 매개변수를 구체화할 때, 배열의 배열 형태라면 any[][]처럼 선언해서 사용하고 함수의 매개변수가 객체이긴 하지만 값을 알 수 없다면 {[key: string]: any}처럼 선언하면 된다.

function hasTwelveLetterKey(o: { [key: string]: any }) {
  for (const key in o) {
    if (key.length === 12) return true;
  }
  return false;
}

✔️최소한으로나마 구체화할 수 있는 방법

type Fn0 = () => any; // 매개변수 없이 호출 가능한 모든 함수
type Fn1 = (arg: any) => any; // 매개변수 1개
type FnN = (...args: any[]) => any; // 모든 개수의 매개변수

[아이템40] 함수 안으로 타입 단언문 감추기

함수 내부에는 타입단언을 사용하고 함수 외부로 드러나는 타입 정의를 정확히 명시하는 정도로 구현하자

declare function shallowEqual(a: any, b: any): boolean;
function shallowObjectEqual<T extends object>(a: T, b: T): boolean {
  for (const [k, aVal] of Object.entries(a)) {
    if (!(k in b) || aVal !== b[k]) {
      // ❌ '{}' 형식에 인덱스 시그니처가 없으므로 요소에 암시적으로 'any' 형식이 있습니다.
      return false;
    }
  }
  return Object.keys(a).length === Object.keys(b).length;
}

if 구문의 k in b 체크로 b객체에 k속성이 있다는 것을 확인했지만 오류가 발생하였다. 실제 오류가 아니라는 것을 알고 있기 때문에 any로 단언하는 수밖에 없다.

declare function shallowEqual(a: any, b: any): boolean;
function shallowObjectEqual<T extends object>(a: T, b: T): boolean {
  for (const [k, aVal] of Object.entries(a)) {
    if (!(k in b) || aVal !== (b as any)[k]) {
      // 정상
      return false;
    }
  }
  return Object.keys(a).length === Object.keys(b).length;
}
profile
Frontend 개발자입니다 😎

0개의 댓글