객체를 순회하는 노하우

TS는 특정 타입에 할당 가능한 모든 경우에 대해 고려되기 때문에, 이 때 단순히 for 키워드를 통해 객체 타입을 순회하려고 하면 타입이 예상치 못하게 추론되는 경우가 있을 수 있습니다.

interface ABC {
  a: string;
  b: string;
  c: number;
}

function foo(abc: ABC) {
  for (const k in abc) {  // const k: string 
                          // 'a' | 'b' | 'c' 가 아닙니다.
    const v = abc[k];
           // ~~~~~~ Element implicitly has an 'any' type
           //        because type 'ABC' has no index signature
  }
}

가령, 위의 매개변수 abc에는 인터페이스 ABC의 타입만 충족한다면 그 외에 추가적으로 어떤 속성을 갖더라도 타입 상으로 문제가 없기 때문에, 이는 정상적인 오류의 출력입니다.

만약, 이러한 타입을 좁히려면 keyof 키워드를 사용하면 됩니다. 단, 이 경우 실제로 해당 객체가 추가적인 키와 값을 가질 가능성이 없는지 판단해야할 필요가 있습니다.

function foo(abc: ABC) {
  let k: keyof ABC;
  for (k in abc) {  // let k: "a" | "b" | "c"
    const v = abc[k];  // Type is string | number
  }
}

타입에 신경쓰지 않고 단순히 객체의 키와 값을 순회하고자 한다면 Object.entries의 사용이 보다 일반적입니다. 물론 이 경우 키와 값의 타입이 추상적이기 때문에, 타입을 다루기에 까다롭습니다.

function foo(abc: ABC) {
  for (const [k, v] of Object.entries(abc)) {
    k  // Type is string
    v  // Type is any
  }
}