blog

Pick 대신 인덱스 접근 타입을 써야 하는 경우

Front-end / TypeScript#TypeScript#Pick#Indexed Access Types#유틸리티 타입

에러

버튼 컴포넌트의 color prop 타입을 재사용하려고 Pick을 썼더니 이런 에러가 났다.

Type 'Pick<CommonBtnProps, "color">' is not assignable to type '"neutralGray" | "brand" | "darkGray" | ... | undefined'.
interface CommonBtnProps {
  color?: 'neutralGray' | 'brand' | 'darkGray' | 'gray';
  size?: 'sm' | 'md';
}

interface IconBtnProps {
  color?: Pick<CommonBtnProps, 'color'>; // ❌
}

원인

Pick<T, K>는 객체 타입을 만든다.

type A = Pick<CommonBtnProps, 'color'>;
// { color?: 'neutralGray' | 'brand' | 'darkGray' | 'gray' }

color 속성에 필요한 것은 문자열 유니온인데, { color?: ... } 객체를 넣었으니 타입이 맞지 않는다.

해결: 인덱스 접근 타입

속성 하나의 값 타입만 꺼내려면 T['key']를 쓴다.

type ButtonColor = CommonBtnProps['color'];
// 'neutralGray' | 'brand' | 'darkGray' | 'gray' | undefined

interface IconBtnProps {
  color?: ButtonColor;
}

선택 속성(?)에서 꺼내면 undefined가 포함된다. 필수 값으로 쓰려면 NonNullable<CommonBtnProps['color']>로 제거한다.

정리

목적사용
일부 속성만 가진 객체 타입Pick<T, 'a' | 'b'>
속성 하나의 값 타입T['a']

Pick은 "props 중 일부만 받는 컴포넌트"처럼 객체 형태를 재사용할 때 쓴다. 예를 들어 interface IconBtnProps extends Pick<CommonBtnProps, 'color'> {}는 올바른 사용이다.