개발/이펙티브 타입스크립트

[이펙티브 타입스크립트+15] 동적 데이터에 인덱스 시그니처 사용하기

Junghyun Kim 2021. 8. 15. 18:17
반응형

2장 타입스크립트의 타입 시스템
아이템 15 | 동적 데이터에 인덱스 시그니처 사용하기

3줄 요약
1. 가능하다면 인덱스 시그니처 사용을 피하자.
2. keys를 알고 있다면 Record 타입 혹은 매핑된 타입 사용을 고려해보자.
3. 외부에서 받아오는 것과 같이 keys가 변동될 수 있다면 인덱스 시그니처 사용을 고려해보자.

참고) 이펙티브 타입스크립트는 타입스크립트의 기본 그 이상을 다룹니다.


이번 아이템의 제목은 동적 데이터에 인덱스 시그니처 사용하기이지만
주제는 동적 데이터가 아니라면 되도록 인덱스 시그니처 사용하지 말자에 가깝습니다.

다들 알고 계시지만 인덱스 시그니처는 아래와 같이 생겼습니다.

// 인덱스 시그니처 타입
type IndexSignatureType = { [property: string]: string };
// [property: string]: string
// (키의 이름)  (키의 타입) (값의 타입)

여기서 property는 키의 위치를 표시하는 용도로 사용됩니다.
그리고 키의 타입이 string으로 표시되었습니다.
값의 타입 또한 string으로 표시된 것을 확인할 수 있습니다.

앞서 아이템 13의 참고 부분에서 인덱스 시그니처를 통해 객체 순환할 때 만나게 되는 에러를 우회하기 위해
인덱스 시그니처를 사용했었다고 말한 적이 있었습니다.
사실, Object.entries를 사용하거나 타입 단언을 사용하는 것이 더 좋습니다.

왜냐하면 인덱스 시그니처를 사용하게 되면 다음과 같은 단점들이 있기 때문입니다.

  1. 모든 키를 허용합니다. 따라서, 객체에는 없는 키를 이용하더라도 타입 체크에서 에러가 나지 않습니다.
  2. 특정 키가 필요하지 않습니다. 따라서, { }와 같이 빈 오브젝트도 할당이 됩니다.
  3. 키마다 다른 타입을 가질 수 없습니다. 따라서, 값의 타입을 유니온 타입을 이용해 타입을 확장시켜야 합니다.
  4. 타입스크립트의 언어 서비스를 제공받을 수 없습니다.

이러한 점 때문에 인덱스 시그니처는 부정확합니다.
따라서, 가능하다면 인덱스 시그니처보다 더 나은 방법을 찾아야 합니다.

타입의 keys들이 무엇이 될지 아는 경우에는 인덱스 시그니처를 사용하는 것보다는 타입을 직접 선언해주는 것이 좋습니다.
번거롭더라도 타입의 안전성을 위해서는 직접 선언해주는 것이 좋습니다.
그리고 그 번거로움을 덜어줄 수 있는 방법들이 몇 가지 있습니다.

첫 번째로, 유틸리티 타입 Record을 사용하는 것입니다.

유틸리티 타입 Record을 통해서 간편하게 타입을 생성할 수 있습니다. 

참고로 Record 타입은 이렇게 생겼습니다.

type Record<K extends keyof any, T> = {
    [P in K]: T;
};

두 번째로, 매핑된 타입을 사용하는 것입니다.

매핑된 타입으로 간편하게 타입을 생성할 수 있습니다.

그리고 매핑된 타입은 조건부 타입을 이용하여 특정 조건에는 다른 타입을 만들어 줄 수 있습니다.

조건부 타입을 이용하여 name 키의 타입을 string 타입으로 설정할 수 있습니다.

이외에 외부로부터 데이터를 받아오는 상황에서 keys가 변동될 가능성이 있다면 인덱스 시그니처 사용을 고려해볼 만합니다.
그리나 사용할 때 주의할 점이 있습니다.
keys가 변동될 수 있기 때문에 값의 타입에 null 혹은 undefined를 유니온 타입으로 넣어주는 것을 고려해야 합니다.
특정 키가 언제든지 사라질 수 있기 때문이지요.

외부 데이터 타입의 값의 타입에 undefined 타입 사용을 고려.

 

Materials From
1. <이펙티브 타입스크립트>(댄 밴더캄 지음, 장원호 옮김, 인사이트 2021)
2. 타입스크립트 공식 홈페이지 | https://www.typescriptlang.org/

 

Typed JavaScript at Any Scale.

TypeScript extends JavaScript by adding types to the language. TypeScript speeds up your development experience by catching errors and providing fixes before you even run your code.

www.typescriptlang.org

 


참고)
인터페이스에서는 매핑된 타입을 사용할 수 없습니다.

인터페이스에서는 매핑된 타입을 사용할 수 없습니다.

 

반응형