TypeScript / / 2024. 11. 2. 00:41

TypeScript 타입조작하기

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

인덱스드 엑세스 타입은 특정 객체 타입에서 필드의 타입을 참조할 때 사용됩니다. 배열이나 객체의 특정 속성에 접근하여 그 타입을 추출하는 방식입니다.

type Person = {
  name: string;
  age: number;
  address: {
    city: string;
    zipcode: number;
  };
};

// Person 타입에서 address 필드의 타입을 가져옴type Address = Person["address"];
// Address 타입은 { city: string; zipcode: number; }// 특정 필드에 접근하여 타입을 가져오기type City = Person["address"]["city"];
// City 타입은 string

주요 사용처

  • 큰 객체의 중첩된 타입에 접근할 때 유용하며, 특정 속성의 타입을 쉽게 재사용하고 싶을 때 사용됩니다.

2. keyof 연산자

keyof 연산자는 객체 타입의 모든 키를 유니온 타입으로 반환합니다. 이 연산자는 인터페이스 또는 객체 타입에서 속성의 이름을 타입으로 사용할 때 매우 유용합니다.

type Person = {
  name: string;
  age: number;
};

// 'name' | 'age' 타입 반환type PersonKeys = keyof Person;

// 키 값에 따라 타입이 결정되는 유틸리티 타입function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const person: Person = { name: "Alice", age: 25 };

// "Alice"const name = getProperty(person, "name");
// 타입이 잘못된 키를 입력하면 오류가 발생함// const invalid = getProperty(person, "height"); // 오류

주요 사용처

  • 객체의 속성 이름을 동적으로 처리하는 유틸리티 함수 작성 시 사용되며, 속성에 대한 키 값에 의존적인 기능을 개발할 때 유용합니다.

3. Mapped 타입

Mapped 타입은 객체의 각 속성을 변환하는 타입입니다. 객체 타입의 모든 속성을 반복하며, 원하는 대로 수정하여 새로운 타입을 생성할 수 있습니다.

type Person = {
  name: string;
  age: number;
};

// 모든 속성을 선택적으로 만드는 Mapped 타입type PartialPerson = {
  [K in keyof Person]?: Person[K];
};

// 모든 속성에 읽기 전용 속성을 추가하는 Mapped 타입type ReadonlyPerson = {
  readonly [K in keyof Person]: Person[K];
};

const person: ReadonlyPerson = { name: "Alice", age: 25 };
// person.name = "Bob"; // 오류: 읽기 전용 속성입니다

주요 사용처

  • 객체 타입의 속성들을 일괄적으로 변경할 때 유용하며, PartialReadonly, **Record**와 같은 유틸리티 타입도 이러한 개념에 기반합니다.

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

템플릿 리터럴 타입은 문자열 리터럴을 사용하여 새로운 타입을 만드는 방법입니다. 문자열 조합을 통해 동적으로 타입을 생성할 수 있습니다.

type Color = "red" | "green" | "blue";

// 템플릿 리터럴을 사용하여 새 타입 생성type ColorVariant = `${Color}-light` | `${Color}-dark`;
// ColorVariant 타입은 "red-light" | "green-light" | "blue-light" | "red-dark" | "green-dark" | "blue-dark"// 타입에 따라 특정 형태의 문자열 생성type Greeting<T extends string> = `Hello, ${T}!`;

type HelloAlice = Greeting<"Alice">;// 타입은 "Hello, Alice!"type HelloBob = Greeting<"Bob">;// 타입은 "Hello, Bob!"

주요 사용처

  • 문자열이 조합된 타입을 생성하거나 특정 포맷을 따르는 문자열 타입을 만들 때 유용합니다.

이 네 가지 타입 조작 기능은 각각 개별적으로 또는 조합하여 사용할 수 있으며, 타입스크립트의 타입 시스템을 더욱 강력하고 유연하게 만듭니다. 이를 통해 안전한 타입 추론과 재사용성을 높일 수 있습니다.

더 상세히 정리

인덱스드 엑세스

ypeScript에서 "인덱스드 액세스 타입(Indexed Access Type)"은 객체 타입의 특정 속성 타입을 참조하거나 추출할 때 사용하는 방식입니다. 이 기능을 통해 객체의 특정 속성 타입을 가져와 재사용하거나 유연하게 타입을 조작할 수 있습니다. 쉽게 말해, 타입[속성명] 형으로 객체 속성의 타입을 가져오는 것을 말합니다.

기본 개념

인덱스드 엑세스 타입을 사용하면 객체 내 특정 속성의 타입을 변수처럼 참조할 수 있습니다. 기본적인 문법은 다음과 같습니다:

type Person = {
  name: string;
  age: number;
  location: string;
};

type AgeType = Person["age"];// number 

위 코드에서 **Person["age"]**는 Person 타입의 age 속성 타입인 **number**를 가져옵니다. **AgeType**은 이제 number 타입으로 정의됩니다.

인덱스드 엑세스 타입의 활용 예

1. 타입 재사용

특정 객체 타입의 속성 중 하나를 여러 곳에서 사용할 때 유용합니다.

type User = {
  id: number;
  username: string;
  email: string;
};

type UserIDType = User["id"];// numberfunction getUserId(id: UserIDType) {
  return id;
}

위 코드에서 **UserIDType**은 User 객체의 id 속성과 같은 number 타입이므로, getUserId 함수에서 이를 재사용할 수 있습니다.

2. 유틸리티 타입과 결합

TypeScript에서 제공하는 keyof 같은 유틸리티 타입과 함께 사용하여 좀 더 유연한 타입 추출이 가능합니다.

type Product = {
  name: string;
  price: number;
  stock: number;
};

type ProductKeys = keyof Product;// "name" | "price" | "stock"type ProductValue = Product[ProductKeys];// string | number

위 예제에서는 **keyof Product**로 Product 타입의 키를 가져왔고, **Product[ProductKeys]**를 사용해 모든 값의 타입을 추출했습니다. 결과적으로 **ProductValue**는 string | number 타입으로 정의됩니다.

인덱스드 엑세스 타입과 조건부 타입

조건부 타입과 결합하여 인덱스드 엑세스 타입을 좀 더 유연하게 사용할 수 있습니다.

type Config = {
  timeout: number;
  baseURL: string;
  headers: { [key: string]: string };
};

type OptionalProperty<T, K extends keyof T> = K extends K ? T[K] | undefined : never;
type ConfigTimeout = OptionalProperty<Config, "timeout">;// number | undefined

OptionalProperty 타입은 T 타입의 특정 키 **K**에 해당하는 값을 | undefined 타입으로 만들어 선택적으로 사용할 수 있게 합니다.

인덱스드 엑세스 타입과 typeof 연산자

**typeof**와 인덱스드 엑세스 타입을 같이 사용하여 객체의 타입을 동적으로 추출할 수 있습니다.

const person = {
  name: "Lee",
  age: 30,
};

type PersonType = typeof person;// { name: string; age: number; }type PersonNameType = PersonType["name"];// string

위 코드에서 **typeof person**을 사용해 person 객체의 타입을 추출했고, **PersonType["name"]**을 통해 name 속성의 타입을 가져왔습니다.

인덱스드 엑세스 타입을 활용한 타입 안전성 강화

인덱스드 엑세스 타입을 사용하면 잘못된 속성 접근을 방지하는 데 유용합니다. 예를 들어, 아래와 같이 특정 속성만 업데이트하는 함수를 정의할 수 있습니다.

type Profile = {
  username: string;
  email: string;
  age: number;
};

function updateProfile<T extends keyof Profile>(field: T, value: Profile[T]) {
// 필드의 타입이 자동으로 Profile[T] 타입에 맞게 강제됩니다.console.log(`${field} updated to ${value}`);
}

updateProfile("username", "JohnDoe");// 정상updateProfile("age", 25);// 정상

이 함수는 **field**에 **Profile**의 속성명만 받을 수 있으며, **value**의 타입 또한 해당 속성의 타입에 맞게 설정됩니다. 이를 통해 타입 안전성을 강화할 수 있습니다.

 

keyof & typeof 연산자

**keyof**와 typeof 연산자는 TypeScript에서 타입을 더 유연하게 다루고, 정적 타입 체킹을 강화하는 데 자주 사용되는 중요한 연산자입니다. 각각 어떤 역할을 하는지, 그리고 어떻게 사용할 수 있는지 자세히 살펴보겠습니다.

1. keyof 연산

keyof 연산자는 객체 타입의 모든 키를 유니언 타입(union type)으로 반환합니다. 이 연산자는 객체 속성의 이름을 문자열 리터럴 유니언 타입으로 만들어, 특정 객체 타입의 키를 다룰 때 매우 유용합니다.

기본 사용 예

객체 타입을 정의한 후, **keyof**를 사용하여 해당 객체 타입의 모든 키를 유니언 타입으로 만들 수 있습니다.

type User = {
  id: number;
  name: string;
  age: number;
};

type UserKeys = keyof User;// "id" | "name" | "age"

위 코드에서 **UserKeys**는 **"id" | "name" | "age"**와 같은 문자열 리터럴 유니언 타입이 됩니다. 이 유니언 타입은 User 타입의 모든 속성 이름을 나타냅니다.

제네릭과 keyof의 조합

**keyof**는 제네릭과 함께 사용할 때 강력합니다. 제네릭을 통해 동적으로 키를 받아 타입을 체크할 수 있습니다.

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const user: User = { id: 1, name: "Alice", age: 30 };
const userName = getProperty(user, "name");// string 타입const userAge = getProperty(user, "age");// number 타입

getProperty 함수는 객체 **obj**와 obj의 키(key)를 받아 해당 키의 타입을 반환합니다. 이로 인해 **userName**은 string, **userAge**는 number 타입으로 자동 추론됩니다.

keyof를 사용하여 타입 안전성 강화

**keyof**는 잘못된 속성 접근을 방지하여 타입 안전성을 높이는 데도 유용합니다.

function updateUser<T extends keyof User>(key: T, value: User[T]) {
// 함수 내부에서 key와 value의 타입이 User의 속성 타입으로 강제됩니다.
}

updateUser("id", 42);// 정상updateUser("name", "Bob");// 정상// updateUser("nonexistent", "value"); // 오류 발생: 존재하지 않는 키

2. typeof 연산자

typeof 연산자는 런타임 값을 타입으로 가져오는 연산자입니다. TypeScript에서 **typeof**를 사용하면 변수나 객체의 타입을 추론하여 다른 타입 정의에서 활용할 수 있습니다.

기본 사용 예

JavaScript의 **typeof**와 비슷해 보이지만, TypeScript의 **typeof**는 타입 정의에서만 사용됩니다.

const user = {
  id: 1,
  name: "Alice",
  age: 30,
};

type UserType = typeof user;
// UserType은 { id: number; name: string; age: number; } 타입이 됩니다.

위 예제에서 **typeof user**는 user 객체의 타입인 **{ id: number; name: string; age: number; }**를 가져옵니다. **UserType**은 이제 **user**와 같은 구조의 타입으로 정의됩니다.

typeof와 함수 타입 정의

**typeof**는 함수의 타입을 추출할 때도 사용할 수 있습니다.

function add(a: number, b: number): number {
  return a + b;
}

type AddFunctionType = typeof add;// (a: number, b: number) => number

위 코드에서 **typeof add**는 add 함수의 타입을 가져옵니다. **AddFunctionType**은 add 함수와 같은 (a: number, b: number) => number 타입이 됩니다.

typeof와 keyof의 조합

**typeof**와 **keyof**를 함께 사용하면 객체 속성의 이름을 추출하는 데 매우 유용합니다.

const config = {
  apiUrl: "<https://api.example.com>",
  timeout: 5000,
};

type ConfigKeys = keyof typeof config;// "apiUrl" | "timeout"

위 예제에서 **typeof config**는 config 객체의 타입을 가져오고, **keyof**를 통해 해당 타입의 키들을 추출하여 **"apiUrl" | "timeout"**이라는 유니언 타입을 얻습니다.

예제: 객체의 키와 값을 동적으로 가져오기

**typeof**와 **keyof**를 함께 사용하여 객체의 키와 값 타입을 동적으로 다룰 수 있습니다.

const settings = {
  theme: "dark",
  version: 1,
};

function getSetting<T extends keyof typeof settings>(key: T): typeof settings[T] {
  return settings[key];
}

const theme = getSetting("theme");// theme의 타입은 stringconst version = getSetting("version");// version의 타입은 number

getSetting 함수는 settings 객체의 키를 받고, 해당 키에 맞는 값을 반환합니다. 이 함수는 settings 객체의 구조에 따라 타입이 자동으로 지정되므로, 코드의 유지보수와 타입 안전성을 높입니다.


요약

  • keyof: 객체 타입의 모든 키를 유니언 타입으로 반환하여 특정 객체 타입의 속성 이름을 다룰 수 있게 합니다.
  • typeof: 변수나 객체의 타입을 추론하여 동적으로 타입을 생성할 수 있게 해줍니다. 특히 기존 변수의 구조를 재사용하여 타입을 선언할 때 유용합니다.

두 연산자를 조합하면 타입 정의를 더 정교하게 작성할 수 있고, 동적 타입 추론을 강화하여 더욱 안전하고 유연한 코드를 작성할 수 있습니다.

 

맵드 타입

TypeScript의 맵드 타입(Mapped Types)은 기존 타입을 기반으로 새로운 타입을 생성하는 방법입니다. 객체의 키와 타입을 재구성하여, 새로운 타입을 효율적으로 정의할 수 있습니다. 주로 기존의 객체 타입을 복사하거나, 특정 속성을 수정하거나 추가할 때 유용하게 사용됩니다.

기본 문법

맵드 타입은 type 키워드 뒤에 제네릭 매개변수와 in 키워드를 사용하여 정의합니다. 예를 들어, type NewType = { [Key in 기존키]: 값 } 형태로 사용합니다.

type Person = {
  name: string;
  age: number;
};

type ReadonlyPerson = {
  readonly [Key in keyof Person]: Person[Key];
};

위 예제에서 ReadonlyPerson은 Person 타입의 모든 키(keyof Person)를 가져와 **readonly**를 붙인 새로운 타입으로 만듭니다. 이제 ReadonlyPerson의 모든 속성은 읽기 전용(readonly) 속성이 됩니다.

맵드 타입의 주요 활용법

1. readonly 속성 적용하기

객체의 모든 속성을 읽기 전용으로 바꾸고 싶을 때 맵드 타입을 사용할 수 있습니다.

type Person = {
  name: string;
  age: number;
};

type ReadonlyPerson = {
  readonly [Key in keyof Person]: Person[Key];
};

// 사용 예시const person: ReadonlyPerson = { name: "Alice", age: 25 };
// person.age = 30; // 오류 발생: 'age'는 읽기 전용 속성입니다.

readonly 속성을 모든 속성에 추가하여 값을 변경할 수 없게 만듭니다.

2. 선택적 속성(?)으로 변경

모든 속성을 선택적으로 만들려면 맵드 타입과 **?**를 함께 사용할 수 있습니다.

type Person = {
  name: string;
  age: number;
};

type PartialPerson = {
  [Key in keyof Person]?: Person[Key];
};

// 사용 예시const partialPerson: PartialPerson = { name: "Alice" };// 'age'가 없어도 오류가 발생하지 않음

PartialPerson 타입의 모든 속성은 선택적으로 변경되어, 속성이 없어도 타입 오류가 발생하지 않습니다.

3. 모든 속성 타입을 다른 타입으로 변환하기

맵드 타입을 사용하여 모든 속성의 타입을 일괄적으로 다른 타입으로 변경할 수 있습니다.

type Person = {
  name: string;
  age: number;
};

type StringifyPerson = {
  [Key in keyof Person]: string;
};

// 사용 예시const person: StringifyPerson = { name: "Alice", age: "25" };// 모든 속성이 문자열 타입

StringifyPerson 타입의 모든 속성은 string 타입으로 변환됩니다.

맵드 타입과 유틸리티 타입

TypeScript는 자주 사용되는 맵드 타입들을 미리 정의한 유틸리티 타입들을 제공합니다. 대표적으로 Readonly<T>Partial<T>Required<T>Record<K, T>Pick<T, K>Omit<T, K> 등이 있습니다.

유틸리티 타입 예시

  • Readonly<T>: 모든 속성을 읽기 전용으로 만듭니다.
  • Partial<T>: 모든 속성을 선택적으로 만듭니다.
  • Required<T>: 모든 선택적 속성을 필수 속성으로 만듭니다.
  • Record<K, T>: 주어진 키들로 구성된 객체 타입을 정의합니다.
  • Pick<T, K>: 특정 속성만 선택하여 새로운 타입을 만듭니다.
  • Omit<T, K>: 특정 속성을 제외한 새로운 타입을 만듭니다.
type Person = {
  name: string;
  age?: number;
};

// Partial을 사용하면 모든 속성이 선택적으로 바뀝니다.type PartialPerson = Partial<Person>;// { name?: string; age?: number; }// Required를 사용하면 모든 속성이 필수로 바뀝니다.type RequiredPerson = Required<Person>;// { name: string; age: number; }// Pick을 사용하여 특정 속성만 선택합니다.type NameOnly = Pick<Person, "name">;// { name: string; }// Omit을 사용하여 특정 속성을 제외합니다.type WithoutAge = Omit<Person, "age">;// { name: string; }

고급 맵드 타입 활용법

맵드 타입은 조건부 타입과 결합하여 더 강력하게 사용할 수 있습니다.

조건부 타입과 함께 사용하기

맵드 타입 내에서 조건부 타입을 활용해 특정 타입에만 변환을 적용할 수 있습니다.

type NullablePerson = {
  [Key in keyof Person]: Person[Key] | null;
};

type FilteredPerson<T> = {
  [Key in keyof T]: T[Key] extends string ? T[Key] : never;
};

type Person = {
  name: string;
  age: number;
};

type StringProperties = FilteredPerson<Person>;// { name: string; age: never }

위 예제에서 **FilteredPerson**은 각 속성 타입이 **string**인 경우에만 해당 속성을 유지하고, 그렇지 않은 속성은 **never**로 변환합니다. **StringProperties**는 name 속성만 남고 **age**는 **never**가 됩니다.

재귀적 맵드 타입

객체 타입의 깊은 속성까지 변환할 때는 재귀적 맵드 타입을 사용할 수 있습니다.

type DeepReadonly<T> = {
  readonly [Key in keyof T]: T[Key] extends object ? DeepReadonly<T[Key]> : T[Key];
};

type NestedPerson = {
  name: string;
  details: {
    age: number;
    address: {
      city: string;
      country: string;
    };
  };
};

type ReadonlyNestedPerson = DeepReadonly<NestedPerson>;
// 모든 속성이 깊은 레벨까지 읽기 전용으로 변경됩니다.

DeepReadonly 타입은 object 타입의 속성이 있을 경우 재귀적으로 **readonly**를 적용하여 모든 중첩 속성까지 읽기 전용으로 만듭니다.


요약

  • 맵드 타입은 기존 객체 타입을 변형하여 새로운 타입을 만드는 데 유용합니다.
  • readonly?, 기타 타입 변환을 통해 객체 속성을 손쉽게 재구성할 수 있습니다.
  • 유틸리티 타입(ReadonlyPartialRequired 등)은 맵드 타입의 주요 활용 예제를 미리 구현해놓은 타입으로, 코드 가독성과 생산성을 높여줍니다.
  • 조건부 타입과 재귀적 맵드 타입을 결합하면 더욱 강력하고 유연한 타입 시스템을 구현할 수 있습니다.

맵드 타입을 사용하면 타입 변형과 관련된 로직을 추상화할 수 있어, 코드 유지보수와 타입 안전성을 높이는 데 큰 도움이 됩니다.

 

템플릿 리터럴 타입

TypeScript의 **템플릿 리터럴 타입(Template Literal Type)**은 문자열 템플릿을 사용하여 새로운 문자열 리터럴 타입을 만드는 기능입니다. JavaScript의 템플릿 문자열 문법과 비슷하지만, TypeScript에서는 타입 레벨에서 사용할 수 있으며, 주로 타입을 조합하거나 변형할 때 사용됩니다.

템플릿 리터럴 타입은 TypeScript 4.1부터 도입되었고, 이를 통해 문자열 리터럴 타입을 결합, 변형 또는 추가적인 타입 연산을 할 수 있습니다.

기본 문법

템플릿 리터럴 타입의 기본 문법은 다음과 같습니다. 문자열 리터럴 타입을 백틱(```) 안에 중괄호({})로 감싸 표현합니다.

type HelloWorld = `Hello, ${string}`;
// HelloWorld 타입은 'Hello, '로 시작하는 모든 문자열 리터럴 타입이 됩니다.

위 예제에서 HelloWorld 타입은 **"Hello, "**로 시작하는 문자열 리터럴 타입으로, 예를 들어 "Hello, Alice" 또는 "Hello, Bob" 같은 문자열을 가질 수 있습니다.

템플릿 리터럴 타입의 주요 사용 예제

1. 문자열 리터럴 타입의 조합

기존의 문자열 리터럴 타입을 조합하여 새로운 타입을 만들 수 있습니다.

type Color = "red" | "green" | "blue";
type Brightness = "light" | "dark";

type Theme = `${Brightness}-${Color}`;
// Theme 타입은 "light-red" | "light-green" | "light-blue" | "dark-red" | "dark-green" | "dark-blue" 형태가 됩니다.

위 코드에서 Theme 타입은 **Brightness**와 Color 타입을 조합하여 모든 가능한 문자열 조합을 생성합니다.

2. 동적 속성명 타입 만들기

객체의 속성 이름에 템플릿 리터럴 타입을 사용할 수 있습니다. 예를 들어, 여러 필드 이름이 비슷한 패턴으로 되어 있는 경우 유용합니다.

type Sizes = "small" | "medium" | "large";

type PaddingProps = {
  [Size in Sizes as `padding-${Size}`]: number;
};

// PaddingProps 타입은 다음과 같은 형태가 됩니다:// {//   "padding-small": number;//   "padding-medium": number;//   "padding-large": number;// }

PaddingProps 타입은 smallmedium, **large**에 각각 padding- 접두사를 붙여 속성 이름을 생성합니다.

3. 함수 타입의 리턴 타입 이름 만들기

템플릿 리터럴 타입을 사용하면, 함수의 리턴 타입이나 속성 이름을 자동으로 생성할 수 있습니다.

type Method = "get" | "post" | "put" | "delete";

type ApiEndpoint = `${Method}Request`;
// ApiEndpoint 타입은 "getRequest" | "postRequest" | "putRequest" | "deleteRequest"가 됩니다.

위 예제에서 ApiEndpoint 타입은 각 HTTP 메소드에 **Request**를 붙인 이름을 생성합니다.

고급 템플릿 리터럴 타입 활용법

템플릿 리터럴 타입은 조건부 타입, 유니언 타입, 맵드 타입과 결합하여 강력한 타입 조합을 할 수 있습니다.

4. 조건부 타입과의 결합

조건부 타입을 활용해 특정 문자열 패턴에 맞는 타입을 만들 수 있습니다.

type Event = "click" | "focus" | "blur";

type EventHandler<T extends Event> = T extends "click" ? `on${Capitalize<T>}` : `handle${Capitalize<T>}`;

// EventHandler<"click">은 "onClick" 타입이 됩니다.// EventHandler<"focus">은 "handleFocus" 타입이 됩니다.

위 코드에서 EventHandler 타입은 **"click"**일 때만 **onClick**을, 그 외에는 **handleFocus**와 **handleBlur**를 생성합니다.

5. 맵드 타입과의 결합

맵드 타입과 템플릿 리터럴 타입을 결합하여 객체의 속성 이름을 동적으로 생성할 수 있습니다.

type UserRole = "admin" | "user" | "guest";

type Permissions = {
  [Role in UserRole as `can${Capitalize<Role>}`]: boolean;
};

// Permissions 타입은 다음과 같은 형태가 됩니다:// {//   canAdmin: boolean;//   canUser: boolean;//   canGuest: boolean;// }

이렇게 하면 **UserRole**의 각 역할에 따라 canAdmincanUsercanGuest 속성의 타입이 **boolean**으로 설정됩니다.

템플릿 리터럴 타입과 유틸리티 타입의 활용

TypeScript는 Uppercase<T>Lowercase<T>Capitalize<T>Uncapitalize<T> 같은 문자열 조작 유틸리티 타입을 제공하여, 템플릿 리터럴 타입과 함께 사용할 수 있습니다.

type Name = "hello world";

type UppercaseName = Uppercase<Name>;// "HELLO WORLD"type CapitalizedName = Capitalize<Name>;// "Hello world"type LowercaseName = Lowercase<Name>;// "hello world"

이러한 유틸리티 타입은 텍스트 변환이 필요한 경우 매우 유용합니다.

예제: API 엔드포인트 타입 생성

예를 들어, API 엔드포인트를 다루는 타입을 정의할 때 템플릿 리터럴 타입을 활용해 각 메소드별 엔드포인트를 쉽게 정의할 수 있습니다.

type HttpMethod = "GET" | "POST";
type ApiPath = "/users" | "/posts";

type ApiEndpoint = `${HttpMethod} ${ApiPath}`;
// ApiEndpoint 타입은 "GET /users" | "GET /posts" | "POST /users" | "POST /posts"가 됩니다.

템플릿 리터럴 타입을 이용한 정교한 문자열 검사

템플릿 리터럴 타입은 특정 패턴의 문자열을 검사하는 데도 사용할 수 있습니다.

type HexColor = `#${string}`;
type IsValidHex<T extends string> = T extends HexColor ? true : false;

type ValidColor = IsValidHex<"#FF5733">;// truetype InvalidColor = IsValidHex<"FF5733">;// false

위 예제에서 IsValidHex 타입은 **#**로 시작하는 문자열인지 검사하여, 조건에 맞으면 true, 맞지 않으면 **false**로 평가됩니다.


요약

  • 템플릿 리터럴 타입은 기존 문자열 리터럴 타입을 조합하여 새로운 타입을 생성하는 기능을 제공합니다.
  • 주요 기능: 문자열 리터럴 조합, 동적 속성명 생성, 문자열 패턴 검증 등
  • 활용: 맵드 타입, 조건부 타입, 유틸리티 타입과 결합해 복잡한 문자열 구조를 생성하고 검사하는 데 유용합니다.

템플릿 리터럴 타입은 반복적인 문자열 타입 정의를 줄이고, 문자열 패턴을 엄격하게 관리하는 데 큰 도움을 줍니다. TypeScript를 활용한 타입 시스템의 확장성과 안전성을 강화할 수 있는 중요한 도구입니다.

'TypeScript' 카테고리의 다른 글

TypeScript 유틸리티 타입  (1) 2024.11.03
TypeScript 조건부 타입  (1) 2024.11.03
TypeScript 제네릭2  (0) 2024.10.29
TypeScript 제네릭1  (1) 2024.10.29
TypeScript 인터페이스로 구현하는 클래스  (0) 2024.10.29
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유