인덱스드 액세스 타입

인덱스드 액세스 타입 (Indexed Access Types)

도입

타입 안에 들어 있는 어떤 속성의 타입만 꺼내 쓰고 싶을 때가 있어요. 그럴 때 Type["key"]처럼 대괄호로 키를 찍어 주면, 그 속성의 타입을 그대로 가져올 수 있는데요. 이게 바로 인덱스드 액세스 타입이에요. 코드가 길어질수록 한 번 정의해 둔 타입에서 필요한 조각만 뽑아 쓰는 게 무척 편리해져요.

출처: TypeScript 공식문서

본문

다른 타입에서 특정 속성의 타입을 조회할 때 인덱스드 액세스 타입을 사용해요.

type Person = { age: number; name: string; alive: boolean };
type Age = Person["age"];
type Age = number

인덱싱에 쓰는 타입은 그 자체로 타입이기 때문에, 유니온이나 keyof, 혹은 다른 모든 타입을 그대로 사용할 수 있어요.

type I1 = Person["age" | "name"];

type I2 = Person[keyof Person];

type AliveOrName = "alive" | "name";
type I3 = Person[AliveOrName];
type I1 = string | number
type I2 = string | number | boolean
type I3 = string | boolean

존재하지 않는 속성을 인덱싱하려고 하면 오류가 나는 것도 확인할 수 있어요.

type I1 = Person["alve"];
// Property 'alve' does not exist on type 'Person'.

임의 타입으로 인덱싱하는 또 다른 예로, number를 써서 배열의 요소 타입을 가져올 수 있어요. 여기에 typeof를 함께 조합하면 배열 리터럴의 요소 타입을 아주 편하게 잡아낼 수 있고요.

const MyArray = [
  { name: "Alice", age: 15 },
  { name: "Bob", age: 23 },
  { name: "Eve", age: 38 },
];

type Person = typeof MyArray[number];
type Age = typeof MyArray[number]["age"];
// Or
type Age2 = Person["age"];
type Person = {
    name: string;
    age: number;
}
type Age = number
type Age2 = number

인덱싱에는 오직 타입만 사용할 수 있어요. 다시 말해, 값을 담는 const 변수로는 참조할 수 없다는 뜻이에요.

const key = "age";
type Age = Person[key];
// Type 'key' cannot be used as an index type.
// 'key' refers to a value, but is being used as a type here. Did you mean 'typeof key'?

그래도 비슷한 방식의 리팩터링을 원한다면, 변수 대신 타입 별칭을 쓰면 돼요.

type key = "age";
type Age = Person[key];

더 알아보기