TypeScript - 키오브 타입 연산자

안녕하세요, 야심 찬 프로그래머 여러분! 오늘 우리는 TypeScript의 세계로 여행을 떠나 یکی از 강력한 기능인 keyof 타입 연산자를 탐구해보겠습니다. 프로그래밍 초보자라도 걱정하지 마세요; 이 개념을 단계별로 안내해드릴게요. 수업을 통해 수많은 학생들에게 가르쳐온 경험을 바탕으로 말입니다. 그럼 커피 한 잔 따고(또는 좋아하는 음료를 마시며), 함께 들어보겠습니다!

TypeScript - Keyof Type Operator

keyof 타입 연산자는 무엇인가요?

본격적인 내용에 들어가기 전에 keyof 타입 연산자가 무엇인지 이해해보겠습니다. 상상해보세요, 보물 상자(프로그래밍에서는 객체라고 부릅니다)가 있고, 이를 열 수 있는 모든 키를 알고 싶어요. 그게 exactly keyof 타입 연산자가 하는 일입니다. 객체 타입의 모든 "키"(속성 이름)를 제공해줍니다.

간단한 비유

책 목차를 생각해보세요. keyof 연산자는 "이 책에서 다루는 모든 주제는 무엇인가요?"라고 묻는 것과 같습니다. 이를 통해 목차에 있는 모든 항목을 얻습니다.

문법

keyof 타입 연산자를 사용하는 문법은 간단합니다:

 type Keys = keyof ObjectType;

여기서 ObjectType는 관심 있는 객체 타입이고, KeysObjectType의 모든 속성 이름의 유니언 타입이 됩니다.

예제

keyof이 어떻게 작동하는지 이해하기 위해 몇 가지 예제를 보겠습니다. 간단한 것부터 시작해 점차 복잡도를 높여갈게요.

예제 1: 기본 사용

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

 type PersonKeys = keyof Person;

 // PersonKeys는 다음과 동일합니다: "name" | "age" | "city"

이 예제에서 우리는 세 개의 속성을 가진 Person 인터페이스를 정의했습니다. keyof Person을 사용하면 TypeScript는 Person의 모든 속성 이름의 유니언 타입을 제공합니다.

예제 2: 변수와 함께 사용

 const person: Person = {
   name: "Alice",
   age: 30,
   city: "Wonderland"
 };

 function getProperty(obj: Person, key: keyof Person) {
   return obj[key];
 }

 console.log(getProperty(person, "name")); // 출력: Alice
 console.log(getProperty(person, "age"));  // 출력: 30
 // console.log(getProperty(person, "job")); // 오류: 인자의 타입 '"job"'은 'keyof Person'에 할당할 수 없습니다.

여기서 우리는 getProperty 함수를 만들어 Person 객체와 Person의 키를 받습니다. TypeScript는 우리가 Person의 유효한 키만 사용하도록 보장하여 컴파일 시 오류를 방지합니다.

예제 3: 동적 속성 접근

 function pluck<T, K extends keyof T>(obj: T, keys: K[]): T[K][] {
   return keys.map(key => obj[key]);
 }

 const car = {
   make: "Toyota",
   model: "Corolla",
   year: 2020
 };

 const result = pluck(car, ["make", "year"]);
 console.log(result); // 출력: ["Toyota", 2020]

이 더 복잡한 예제에서 우리는 pluck 함수를 만들어 어떤 객체 타입에도 작동할 수 있게 했습니다. 이 함수는 객체와 그 키의 배열을 받아 해당 키에 해당하는 값을 배열로 반환합니다.

예제 4: keyof와 매apped 타입을 결합

 type Optional<T> = {
   [K in keyof T]?: T[K];
 };

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

 type OptionalUser = Optional<User>;

 // OptionalUser는 다음과 동일합니다:
 // {
 //   id?: number;
 //   name?: string;
 //   email?: string;
 // }

 const partialUser: OptionalUser = { name: "Bob" }; // 이는 유효합니다

여기서 우리는 모든 속성을 선택 사항으로 만드는 유틸리티 타입 Optional을 만들었습니다. keyof를 매apped 타입과 결합하여 이를 실현했습니다.

메서드 표

여기서 다루었던 주요 메서드와 개념을 요약한 표입니다:

메서드/개념 설명 예제
keyof 객체 타입의 모든 속성 이름의 유니언 타입을 반환합니다 type Keys = keyof Person
속성 접근 keyof를 사용하여 객체 속성을 접근합니다 obj[key as keyof ObjectType]
제네릭 제약 keyof를 사용하여 제네릭 타입을 제약합니다 K extends keyof T
매apped 타입 keyof를 매apped 타입과 결합하여 타입 변환을 수행합니다 [K in keyof T]?: T[K]

결론

그렇습니다, 여러분! 우리는 TypeScript의 keyof 타입 연산자의 세계를 여행했습니다. 기본 사용에서 고급 시나리오까지, 이 강력한 연산자가 코드를 더 안전하고 유연하게 만드는 방법을 보셨습니다.

기억하세요, 새로운 기술을 배우는 것은 연습이 필요합니다. 즉시 이해되지 않더라도 낙담하지 마세요. 다양한 예제를 실험하고 시도하면 곧 keyof를 마스터하실 것입니다!

항상 학생들에게 말하듯이, 코딩은 요리와 같습니다. 이해하는 인자(개념)가 많을수록, 만드는 레시피(프로그램)가 더 효율적이고 견고해집니다. 그러니 TypeScript의 그릇을 계속 저어가며, 행복한 코딩을 기원합니다!

Credits: Image by storyset