본문으로 바로가기
윤창원uiwwsw · 작은 우주

개발과 기술

Object.entries의 키 타입을 보완하기 — typedEntries의 조건과 한계

2026-09-10: 설명과 코드 예시를 보완했습니다. 아래 예시는 글의 설계 의도를 전달하기 위한 것이며, 원 프로젝트에 반영된 변경 내역과는 구분합니다.

객체를 순회할 때 Object.entries()를 자주 쓴다. 그런데 키를 확인한 뒤 그 키에 맞는 값의 메서드를 쓰려면 타입이 아쉬울 때가 있다. 값이 유니온으로 추론되더라도, 어느 키에 어느 값이 대응하는지까지 그대로 유지되지는 않을 수 있기 때문이다.

const user = { name: 'Alice', age: 30 };
const entries = Object.entries(user);
// 키는 string으로 넓어진다.
// 값의 타입은 적용되는 라이브러리 선언과 인자 타입에 따라 달라진다.

반환값이 언제나 [string, any][]인 것은 아니다. 여기서 보완하고 싶은 부분은 더 구체적이다. name이면 문자열이고, age이면 숫자라는 관계를 순회 중에도 사용하고 싶다. 그렇다고 순회할 때마다 긴 타입 단언을 반복해서 쓰고 싶지는 않다. 그 부분을 작은 함수 하나로 모았다.

닫힌 객체에 사용하는 보조 함수

다음 예시는 문자열 키만 가진 일반 객체를 대상으로 한다. 해당 값에 선언된 키 외의 enumerable 속성이 없다는 조건을 호출자가 알고 있을 때 사용하는 타입 단언이다.

type StringEntry<T extends object> = {
  [K in Extract<keyof T, string>]-?: [K, T[K]]
}[Extract<keyof T, string>];

export function typedEntries<T extends object>(obj: T): StringEntry<T>[] {
  return Object.entries(obj) as StringEntry<T>[];
}

const user = { name: 'Alice', age: 30 };
for (const [key, value] of typedEntries(user)) {
  if (key === 'age') {
    value.toFixed();
  }
}

각 키의 튜플을 유니온으로 만들었기 때문에 키를 좁혔을 때 연결된 값도 좁힐 수 있다. [keyof T, T[keyof T]] 하나로 표현하면 키와 값 각각의 유니온은 남지만 이 대응 관계는 약해진다.

단언이 보장하지 않는 것

TypeScript의 객체 타입은 런타임 속성 목록을 봉인하지 않는다. TypeScript 객체 타입

const full = { name: 'Alice', age: 30 };
const named: { name: string } = full;
Object.entries(named); // 런타임에는 age도 포함된다.

이 값에 typedEntries(named)를 적용하면 타입에는 없는 age가 실제로 나타난다. 보조 함수에 as를 모았다고 런타임 검증이 생긴 것은 아니다.

숫자 키는 문자열로 반환되고, Symbol 키는 Object.entries 대상이 아니다. 이 예시는 이런 객체나 배열, 임의의 외부 응답을 모두 다루는 범용 함수로 사용하면 안 된다.

외부 데이터라면 스키마를 확인하거나 필요한 키를 명시해 순회하는 방법을 고려할 수 있다. 타입에 적힌 키와 실제로 열거될 키가 같은지 먼저 확인해야 한다.

그 조건을 아는 내부 객체에서는 이 짧은 함수가 제법 편하다. 매번 같은 as를 길게 적는 대신, 필요한 단언을 한곳에 두고 순회하는 코드에는 순회할 내용만 남길 수 있으니까.

Assisted by AI

© uiwwsw · 본인 소유의 글·이미지에 대한 무단 복제·재게시를 허용하지 않습니다. 개인 열람·원문 링크 공유·검색 색인과 제한적인 미리보기는 허용합니다. 법령상 이용 예외, 기존 이용 허락, 코드·제삼자 자료의 기존 라이선스는 유지합니다. 콘텐츠 이용 안내

무단 복제·재게시를 허용하지 않습니다. 콘텐츠 이용 안내

윤창원이 벨로그에 남긴 글을 이 작은 우주에도 모았습니다. 사진은 누르면 원본 크기로 볼 수 있습니다. 원문의 전체 서식 보기 ↗

모든 글 둘러보기 →