TypeScript

[TypeScript] 타입스크립트 타입조작

깅민 2025. 5. 27. 11:28

1. 인덱스드 엑세스 타입

인덱스를 이용해 타입의 특정 프로퍼티에 접근하는 방법입니다.

객체, 배열, 튜플에 사용할 수 있습니다.

1-1. 객체

interface Post {
  createdAt: string,
  modifiedAt: string,
  user: {
    id: number,
    name: string
  }
}

const post: Post = {
  createdAt: "2025-05-27",
  modifiedAt: "2025-05-27",
  user: {
    id: 1,
    name: "a"
  }
}

function getUserInfo(user: { id: number; name: string }) {
  console.log(`id: ${user.id} name: ${user.name}`);
}

 

위와 같은 객체에서(post) user 에 프로퍼티가 하나 추가된다고 하면

아래 처럼 추가해줘야 할 겁니다.

불편하죠.

interface Post {
  createdAt: string,
  modifiedAt: string,
  user: {
    id: number,
    name: string,
    gender: string
  }
}

const post: Post = {
  createdAt: "2025-05-27",
  modifiedAt: "2025-05-27",
  user: {
    id: 1,
    name: "a",
    gender: "m"
  }
}

function getUserInfo(user: { id: number; name: string, gender: string }) {
  console.log(`id: ${user.id} name: ${user.name} gender: ${user.gender}`);
}

 

인덱스드 엑세스를 이용하면 다음과 같이 쓸 수 있습니다.

타입은 { id: number, name: string, gender: string } 이 됩니다.

function getUserInfo(user: Post["user"]) {
  console.log(`id: ${user.id} name: ${user.name} gender: ${user.gender}`);
}

getUserInfo(post.user);
// id: 1 name: a gender: m

 

"user" 가 인덱스 입니다.

주의할 점은 변수로 사용하면 에러가 납니다.

const user = "user";

function getUserInfo(user: Post[user]) { // 에러
  console.log(`id: ${user.id} name: ${user.name} gender: ${user.gender}`);
}

 

1-2. 배열

type PostList = {
  createdAt: string;
  modifiedAt: string;
  user: {
    id: number;
    name: string;
    gender: string;
  };
}[];

const post: PostList[number] = {
  createdAt: "2025-05-27",
  modifiedAt: "2025-05-27",
  user: {
    id: 1,
    name: "a",
    gender: "m",
  },
};

console.log(post);
// {
//   createdAt: '2025-05-27',
//   modifiedAt: '2025-05-27',
//   user: { id: 1, name: 'a', gender: 'm' }
// }

 

1-3. 튜플

type Test = [number, string, boolean];

type Test0 = Test[0];
// number

 

2. keyof

keyof 타입

형태로 사용합니다.

key를 String Literal Union 타입으로 추출합니다.

 

아래 코드에서 key는 "name" | "price" 입니다.

interface Jacket {
  name: string;
  price: number;
}

function getJacket(jacket: Jacket, key: keyof Jacket) {
  return jacket[key];
}

const jacket: Jacket = {
  name: "test",
  price: 1,
};

console.log(getJacket(jacket, "name"));
// test

 

typeof와 함께 쓸 수 있습니다.

typeof로 객채의 타입을 추론해서 타입을 만들 수 있습니다.

const person = {
  name: "Alice",
  age: 30,
  isAdmin: true,
};

type Person = typeof person;
// => { name: string; age: number; isAdmin: boolean }

type PersonKeys = keyof Person;
// => "name" | "age" | "isAdmin"

// { name: string; age: number; isAdmin: boolean }
function getPerson(person: Person, key: keyof typeof person) {
  return person[key];
}
console.log(getPerson(person, "age"));

 

3. 맵드

맵드 타입은 이렇게 정의할 수 있습니다.

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

type PartialUser = {
  [key in "id" | "name" | "age"]?: User[key];
};

 

타입은 아래와 같은 타입으로 됩니다.

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

 

keyof 연산자를 사용하면 더 간단히 쓸 수 있습니다.

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

type PartialUser = {
  [key in keyof User]?: User[key];
};

 

4. 템플릿 리터럴

경우의 수가 많아질 경우 간단하게 타입을 정의할 수 있는 방법입니다.

type Number = "one" | "two" | "three";
type Color = "white" | "red" | "green";

type NumberColor = "one-white" | "one-red" | "one-green"; // ...

 

템플릿을 활용하면 이렇게 바꿀 수 있습니다.

type NumberColor = `${Number}-${Color}`;