TypeScript

[TypeScript] 타입 조작하기

2025년 11월 29일
1
TypeScriptStudyTypeManipulationAdvancedTypes

📑 목차

타입스크립트에는 기본 타입을 상황에 따라 유동적으로 변환할 수 있는 강력한 기능들이 있다. 제네릭(Generic)도 그중 하나지만, 이번에는 제네릭과 조건부 타입을 제외한 4가지 핵심 타입 조작 기능을 정리해 본다.

  1. 인덱스드 엑세스 타입 (Indexed Access Types)
  2. keyof 연산자
  3. 맵드 타입 (Mapped Types)
  4. 템플릿 리터럴 타입 (Template Literal Types)

1. 인덱스드 엑세스 타입 (Indexed Access Types)

인덱스를 이용해 다른 타입 내의 특정 프로퍼티 타입을 추출하는 기능이다. 객체, 배열, 튜플에 모두 사용할 수 있다.

1-1. 객체 프로퍼티 타입 추출

게시글(Post) 타입에서 작성자(author)의 타입만 따로 떼어내고 싶을 때 유용하다.

interface Post {
  title: string;
  content: string;
  author: {
    id: number;
    name: string;
    age: number;
  };
}

// Post["author"]를 통해 author 프로퍼티의 타입을 추출
function printAuthorInfo(author: Post["author"]) {
  console.log(`${author.id} - ${author.name}`);
}

이렇게 하면 Post 타입이 수정되더라도 printAuthorInfo 함수의 매개변수 타입을 일일이 수정할 필요가 없다.

주의할 점:

  • 인덱스에는 이 아닌 타입만 들어갈 수 있다. 변수에 담긴 문자열(const key = "author")을 인덱스로 쓸 수 없다.
  • 존재하지 않는 프로퍼티 키를 넣으면 오류가 발생한다.

1-2. 배열 요소 타입 추출

배열 타입 뒤에 [number]를 붙이면 배열 요소의 타입을 추출할 수 있다.

type PostList = {
  title: string;
  content: string;
  author: {
    id: number;
    name: string;
    age: number;
  };
}[];

// 배열의 요소 타입 추출
const post: PostList[number] = {
  title: "게시글 제목",
  content: "게시글 본문",
  author: {
    id: 1,
    name: "조태민",
    age: 25,
  },
};

PostList[0]처럼 리터럴 숫자를 넣어도 동일하게 동작한다.


2. keyof 연산자

객체 타입으로부터 모든 프로퍼티의 키(Key)를 String Literal Union 타입으로 추출하는 연산자다.

interface Person {
  name: string;
  age: number;
  location: string;
}

// keyof Person 결과: "name" | "age" | "location"
function getPropertyKey(person: Person, key: keyof Person) {
  return person[key];
}

프로퍼티가 추가되거나 이름이 바뀌어도 keyof가 자동으로 반영해주므로 유지보수가 매우 편해진다.

꿀팁: typeof와 함께 사용하기

변수의 타입을 가져오는 typeof 연산자와 함께 사용하면 객체 변수로부터 타입을 뽑아내고, 그 키들을 추출할 수 있다.

const person = {
  name: "조태민",
  age: 25,
};

// typeof person -> Person 객체 타입 추론
// keyof typeof person -> "name" | "age"
function getPropertyKey(person: typeof person, key: keyof typeof person) {
  return person[key];
}

3. 맵드 타입 (Mapped Types)

기존 객체 타입을 기반으로 새로운 객체 타입을 만드는 기능이다. 자바스크립트의 map 함수와 비슷하게 동작한다.

예를 들어, 모든 프로퍼티를 선택적(?)으로 바꾸는 PartialUser 타입을 만들어보자.

interface User {
  id: number;
  name: string;
  age: number;
}

// 맵드 타입 정의
type PartialUser = {
  [key in keyof User]?: User[key];
};
  • [key in keyof User]: User의 키들(id | name | age)을 순회한다.
  • User[key]: 해당 키의 타입을 가져온다.
  • ?: 모든 프로퍼티를 선택적 속성으로 만든다.

결과적으로 PartialUser는 다음과 같은 타입이 된다 5.

{
  id?: number;
  name?: string;
  age?: number;
}

이를 활용하면 모든 속성을 읽기 전용(readonly)으로 만드는 등 다양하게 변형할 수 있다.

type ReadonlyUser = {
  readonly [key in keyof User]: User[key];
};

4. 템플릿 리터럴 타입 (Template Literal Types)

문자열 리터럴 타입을 조합하여 새로운 문자열 패턴 타입을 만드는 기능이다.

type Color = "red" | "black" | "green";
type Animal = "dog" | "cat" | "chicken";

// 모든 경우의 수 조합 (ex: "red-dog", "black-cat" ...)
type ColoredAnimal = `${Color}-${Animal}`;

일일이 조합을 적지 않아도 ColorAnimal의 모든 가능한 조합을 자동으로 생성해 준다 6.


요약

기능설명예시 문법
인덱스드 엑세스특정 프로퍼티/요소의 타입 추출Type["key"], ArrayType[number]
keyof객체 타입의 키를 유니온으로 추출keyof Type
맵드 타입기존 타입을 순회하며 변형[Key in keyof Type]: Type[Key]
템플릿 리터럴문자열 패턴 조합${TypeA}-${TypeB}

이 기능들을 적절히 활용하면 중복 코드를 줄이고, 유지보수하기 쉬운 유연한 타입을 설계할 수 있다.

@taemni

@taemni

안녕하세요, 차근차근 성장 중인 조태민입니다.

instagram

댓글