TypeScriptμ κ°λ ₯ν ν νλ¦Ώ 리ν°λ΄ νμ μ νμνμ¬ κ³ κΈ λ¬Έμμ΄ μ‘°μ, ν¨ν΄ λ§€μΉ λ° μ ν¨μ± κ²μ¬μ νμ©νμΈμ. μ€μ μ¬λ‘μ μ μ€μΌμ΄μ€λ₯Ό ν΅ν΄ νμ΅ν©λλ€.
ν νλ¦Ώ 리ν°λ΄ νμ : TypeScriptμμμ λ¬Έμμ΄ ν¨ν΄ λ§€μΉ λ° μ ν¨μ± κ²μ¬
TypeScriptμ νμ μμ€ν μ μ§μμ μΌλ‘ λ°μ νλ©°, κ°λ°μμκ² λ³΅μ‘ν λ‘μ§μ νννκ³ νμ μμ μ±μ 보μ₯νκΈ° μν λμ± κ°λ ₯ν λꡬλ₯Ό μ 곡ν©λλ€. μ΅κ·Ό λ²μ μμ λμ λ κ°μ₯ ν₯λ―Έλ‘κ³ λ€μ¬λ€λ₯ν κΈ°λ₯ μ€ νλλ ν νλ¦Ώ 리ν°λ΄ νμ μ λλ€. μ΄ νμ λ€μ νμ λ 벨μμ λ¬Έμμ΄μ μ‘°μν μ μκ² νμ¬, κ³ κΈ λ¬Έμμ΄ ν¨ν΄ λ§€μΉ λ° μ ν¨μ± κ²μ¬λ₯Ό κ°λ₯νκ² ν©λλ€. μ΄λ λμ± κ²¬κ³ νκ³ μ μ§λ³΄μνκΈ° μ¬μ΄ μ ν리μΌμ΄μ μ μμ±ν μ μλ μμ ν μλ‘μ΄ κ°λ₯μ±μ μ΄μ΄μ€λλ€.
ν νλ¦Ώ 리ν°λ΄ νμ μ΄λ 무μμΈκ°μ?
ν νλ¦Ώ 리ν°λ΄ νμ μ JavaScriptμμ ν νλ¦Ώ 리ν°λ΄μ΄ μλνλ λ°©μκ³Ό μ μ¬νκ², λ¬Έμμ΄ λ¦¬ν°λ΄ νμ κ³Ό μ λμ¨ νμ μ κ²°ν©νμ¬ κ΅¬μ±λλ νμ μ ν ννμ λλ€. νμ§λ§ λ°νμ λ¬Έμμ΄μ μμ±νλ λμ , κΈ°μ‘΄ νμ μ κΈ°λ°μΌλ‘ μλ‘μ΄ νμ μ μμ±ν©λλ€.
λ€μμ κΈ°λ³Έμ μΈ μμμ λλ€:
type Greeting<T extends string> = `Hello, ${T}!`;
type MyGreeting = Greeting<"World">; // type MyGreeting = "Hello, World!"
μ΄ μμμμ `Greeting`μ λ¬Έμμ΄ νμ `T`λ₯Ό μ λ ₯μΌλ‘ λ°μ "Hello, ", `T`, κ·Έλ¦¬κ³ "!"μ μ°κ²°μΈ μλ‘μ΄ νμ μ λ°ννλ ν νλ¦Ώ 리ν°λ΄ νμ μ λλ€.
κΈ°λ³Έ λ¬Έμμ΄ ν¨ν΄ λ§€μΉ
ν νλ¦Ώ 리ν°λ΄ νμ μ κΈ°λ³Έμ μΈ λ¬Έμμ΄ ν¨ν΄ λ§€μΉμ μννλ λ° μ¬μ©λ μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ νΉμ ν¨ν΄κ³Ό μΌμΉνλ κ²½μ°μλ§ μ ν¨ν νμ μ μμ±ν μ μμ΅λλ€.
μλ₯Ό λ€μ΄, "prefix-"λ‘ μμνλ λ¬Έμμ΄λ§ νμ©νλ νμ μ μμ±ν μ μμ΅λλ€:
type PrefixedString<T extends string> = T extends `prefix-${string}` ? T : never;
type ValidPrefixedString = PrefixedString<"prefix-valid">; // type ValidPrefixedString = "prefix-valid"
type InvalidPrefixedString = PrefixedString<"invalid">; // type InvalidPrefixedString = never
μ΄ μμμμ `PrefixedString`μ μ‘°κ±΄λΆ νμ μ μ¬μ©νμ¬ μ λ ₯ λ¬Έμμ΄ `T`κ° "prefix-"λ‘ μμνλμ§ νμΈν©λλ€. λ§μ½ κ·Έλ λ€λ©΄, νμ μ `T` μ체μ΄κ³ , κ·Έλ μ§ μλ€λ©΄ `never`μ λλ€. `never`λ TypeScriptμμ λ°μνμ§ μλ κ°μ νμ μ λνλ΄λ νΉλ³ν νμ μΌλ‘, μ ν¨νμ§ μμ λ¬Έμμ΄μ ν¨κ³Όμ μΌλ‘ μ μΈν©λλ€.
λ¬Έμμ΄μ νΉμ λΆλΆ μΆμΆνκΈ°
ν νλ¦Ώ 리ν°λ΄ νμ μ λ¬Έμμ΄μ νΉμ λΆλΆμ μΆμΆνλ λ°μλ μ¬μ©λ μ μμ΅λλ€. μ΄λ λ¬Έμμ΄μμ λ°μ΄ν°λ₯Ό νμ±νμ¬ λ€λ₯Έ νμ μΌλ‘ λ³νν΄μΌ ν λ νΉν μ μ©ν©λλ€.
"x:10,y:20" νμμ μ’νλ₯Ό λνλ΄λ λ¬Έμμ΄μ΄ μλ€κ³ κ°μ ν΄ λ΄ μλ€. ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©νμ¬ x λ° y κ°μ μΆμΆν μ μμ΅λλ€:
type CoordinateString = `x:${number},y:${number}`;
type ExtractX<T extends CoordinateString> = T extends `x:${infer X},y:${number}` ? X : never;
type ExtractY<T extends CoordinateString> = T extends `x:${number},y:${infer Y}` ? Y : never;
type XValue = ExtractX<"x:10,y:20">; // type XValue = 10
type YValue = ExtractY<"x:10,y:20">; // type YValue = 20
μ΄ μμμμ `ExtractX`μ `ExtractY`λ `infer` ν€μλλ₯Ό μ¬μ©νμ¬ `number` νμ κ³Ό μΌμΉνλ λ¬Έμμ΄μ λΆλΆμ μΊ‘μ²ν©λλ€. `infer`λ₯Ό μ¬μ©νλ©΄ ν¨ν΄ λ§€μΉμμ νμ μ μΆμΆν μ μμ΅λλ€. μΊ‘μ²λ νμ μ μ‘°κ±΄λΆ νμ μ λ°ν νμ μΌλ‘ μ¬μ©λ©λλ€.
κ³ κΈ λ¬Έμμ΄ μ ν¨μ± κ²μ¬
ν νλ¦Ώ 리ν°λ΄ νμ μ μ λμ¨ νμ λ° μ‘°κ±΄λΆ νμ κ³Ό κ°μ λ€λ₯Έ TypeScript κΈ°λ₯κ³Ό κ²°ν©νμ¬ κ³ κΈ λ¬Έμμ΄ μ ν¨μ± κ²μ¬λ₯Ό μνν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λ¬Έμμ΄μ ꡬ쑰μ λ΄μ©μ λν 볡μ‘ν κ·μΉμ κ°μ νλ νμ μ μμ±ν μ μμ΅λλ€.
μλ₯Ό λ€μ΄, ISO 8601 λ μ§ λ¬Έμμ΄μ κ²μ¦νλ νμ μ μμ±ν μ μμ΅λλ€:
type Year = `${number}${number}${number}${number}`;
type Month = `0${number}` | `10` | `11` | `12`;
type Day = `0${number}` | `${1 | 2}${number}` | `30` | `31`;
type ISODate = `${Year}-${Month}-${Day}`;
type ValidDate = ISODate extends "2023-10-27" ? true : false; // true
type InvalidDate = ISODate extends "2023-13-27" ? true : false; // false
function processDate(date: ISODate) {
// Function logic here. TypeScript enforces the ISODate format.
return `Processing date: ${date}`;
}
console.log(processDate("2024-01-15")); // Works
//console.log(processDate("2024-1-15")); // TypeScript error: Argument of type '"2024-1-15"' is not assignable to parameter of type '`${number}${number}${number}${number}-${0}${number}-${0}${number}` | `${number}${number}${number}${number}-${0}${number}-${1}${number}` | ... 14 more ... | `${number}${number}${number}${number}-12-31`'.
μ¬κΈ°μ `Year`, `Month`, `Day`λ λ μ§μ κ° λΆλΆμ λν μ ν¨ν νμμ λνλ΄κΈ° μν΄ ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©νμ¬ μ μλ©λλ€. `ISODate`λ μ΄ νμ λ€μ κ²°ν©νμ¬ μ ν¨ν ISO 8601 λ μ§ λ¬Έμμ΄μ λνλ΄λ νμ μ μμ±ν©λλ€. μ΄ μμλ λν μ΄ νμ μ΄ ν¨μμμ λ°μ΄ν° νμμ κ°μ νμ¬ μλͺ»λ λ μ§ νμμ΄ μ λ¬λλ κ²μ λ°©μ§νλ λ° μ΄λ»κ² μ¬μ©λ μ μλμ§ λ³΄μ¬μ€λλ€. μ΄λ μ½λμ μ λ’°μ±μ ν₯μμν€κ³ μλͺ»λ μ λ ₯μΌλ‘ μΈν λ°νμ μ€λ₯λ₯Ό λ°©μ§ν©λλ€.
μ€μ μ¬μ© μ¬λ‘
ν νλ¦Ώ 리ν°λ΄ νμ μ λ€μν μ€μ μλ리μ€μμ μ¬μ©λ μ μμ΅λλ€. λ€μμ λͺ κ°μ§ μμμ λλ€:
- νΌ μ ν¨μ± κ²μ¬: ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©νμ¬ μ΄λ©μΌ μ£Όμ, μ νλ²νΈ λ° μ°νΈ λ²νΈμ κ°μ νΌ μ λ ₯μ νμμ κ²μ¦ν μ μμ΅λλ€.
- API μμ² μ ν¨μ± κ²μ¬: ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©νμ¬ API μμ² νμ΄λ‘λμ ꡬ쑰λ₯Ό κ²μ¦νμ¬ μμ νμμ λΆν©νλμ§ νμΈν μ μμ΅λλ€. μλ₯Ό λ€μ΄, ν΅ν μ½λ("USD", "EUR", "GBP" λ±)λ₯Ό κ²μ¦ν μ μμ΅λλ€.
- μ€μ νμΌ νμ±: ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©νμ¬ μ€μ νμΌμ νμ±νκ³ νΉμ ν¨ν΄μ λ°λΌ κ°μ μΆμΆν μ μμ΅λλ€. μ€μ κ°μ²΄μμ νμΌ κ²½λ‘λ₯Ό κ²μ¦νλ κ²μ κ³ λ €ν΄ λ³΄μΈμ.
- λ¬Έμμ΄ κΈ°λ° Enum: ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©νμ¬ μ ν¨μ± κ²μ¬κ° ν¬ν¨λ λ¬Έμμ΄ κΈ°λ° enumμ μμ±ν μ μμ΅λλ€.
μμ: ν΅ν μ½λ μ ν¨μ± κ²μ¬
ν΅ν μ½λ μ ν¨μ± κ²μ¬μ λν λ μμΈν μμλ₯Ό μ΄ν΄λ³΄κ² μ΅λλ€. μ°λ¦¬λ μ ν리μΌμ΄μ μμ μ ν¨ν ISO 4217 ν΅ν μ½λλ§ μ¬μ©λλλ‘ λ³΄μ₯νκ³ μ ν©λλ€. μ΄λ¬ν μ½λλ μΌλ°μ μΌλ‘ μΈ κ°μ λλ¬Έμμ λλ€.
type CurrencyCode = `${Uppercase<string>}${Uppercase<string>}${Uppercase<string>}`;
function formatCurrency(amount: number, currency: CurrencyCode) {
// Function logic to format currency based on the provided code.
return `$${amount} ${currency}`;
}
console.log(formatCurrency(100, "USD")); // Works
//console.log(formatCurrency(100, "usd")); // TypeScript error: Argument of type '"usd"' is not assignable to parameter of type '`${Uppercase}${Uppercase}${Uppercase}`'.
//More precise example:
type ValidCurrencyCode = "USD" | "EUR" | "GBP" | "JPY" | "CAD" | "AUD"; // Extend as needed
type StronglyTypedCurrencyCode = ValidCurrencyCode;
function formatCurrencyStronglyTyped(amount: number, currency: StronglyTypedCurrencyCode) {
return `$${amount} ${currency}`;
}
console.log(formatCurrencyStronglyTyped(100, "EUR")); // Works
//console.log(formatCurrencyStronglyTyped(100, "CNY")); // TypeScript error: Argument of type '"CNY"' is not assignable to parameter of type '"USD" | "EUR" | "GBP" | "JPY" | "CAD" | "AUD"'.
μ΄ μμλ μΈ κ°μ λλ¬Έμλ‘ κ΅¬μ±λ λ¬Έμμ΄λ§ νμ©νλ `CurrencyCode` νμ μ μμ±νλ λ°©λ²μ 보μ¬μ€λλ€. λ λ²μ§Έ, λμ± κ°λ ₯ν νμ μ§μ μμλ μ΄λ₯Ό 미리 μ μλ νμ© κ°λ₯ν ν΅ν λͺ©λ‘μΌλ‘ λμ± μ ννλ λ°©λ²μ 보μ¬μ€λλ€.
μμ: API μλν¬μΈνΈ κ²½λ‘ μ ν¨μ± κ²μ¬
λ λ€λ₯Έ μ¬μ© μ¬λ‘λ API μλν¬μΈνΈ κ²½λ‘ μ ν¨μ± κ²μ¬μ λλ€. μ ν¨ν API μλν¬μΈνΈ ꡬ쑰λ₯Ό λνλ΄λ νμ μ μ μνμ¬ μμ²μ΄ μ¬λ°λ₯Έ κ²½λ‘λ‘ μ΄λ£¨μ΄μ§λλ‘ λ³΄μ₯ν μ μμ΅λλ€. μ΄λ μ¬λ¬ μλΉμ€κ° λ€λ₯Έ APIλ₯Ό λ ΈμΆν μ μλ λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²μμ νΉν μ μ©ν©λλ€.
type APIServiceName = "users" | "products" | "orders";
type APIEndpointPath = `/${APIServiceName}/${string}`;
function callAPI(path: APIEndpointPath) {
// API call logic
console.log(`Calling API: ${path}`);
}
callAPI("/users/123"); // Valid
callAPI("/products/details"); // Valid
//callAPI("/invalid/path"); // TypeScript error
// Even more specific:
type APIAction = "create" | "read" | "update" | "delete";
type APIEndpointPathSpecific = `/${APIServiceName}/${APIAction}`;
function callAPISpecific(path: APIEndpointPathSpecific) {
// API call logic
console.log(`Calling specific API: ${path}`);
}
callAPISpecific("/users/create"); // Valid
//callAPISpecific("/users/list"); // TypeScript error
μ΄λ₯Ό ν΅ν΄ API μλν¬μΈνΈμ ꡬ쑰λ₯Ό λμ± μ λ°νκ² μ μνμ¬ μ€νλ₯Ό λ°©μ§νκ³ μ ν리μΌμ΄μ μ λ°μ μΌκ΄μ±μ 보μ₯ν μ μμ΅λλ€. μ΄λ κΈ°λ³Έμ μΈ μμμ΄λ©°, 쿼리 λ§€κ°λ³μ λ° URLμ λ€λ₯Έ λΆλΆμ κ²μ¦νκΈ° μν΄ λ 볡μ‘ν ν¨ν΄μ μμ±ν μ μμ΅λλ€.
ν νλ¦Ώ 리ν°λ΄ νμ μ¬μ©μ μ΄μ
λ¬Έμμ΄ ν¨ν΄ λ§€μΉ λ° μ ν¨μ± κ²μ¬μ ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©νλ©΄ λ€μκ³Ό κ°μ μ¬λ¬ μ΄μ μ΄ μμ΅λλ€:
- ν₯μλ νμ μμ μ±: ν νλ¦Ώ 리ν°λ΄ νμ μ λ¬Έμμ΄μ λν λ μ격ν νμ μ μ½μ μ μ©νμ¬ λ°νμ μ€λ₯μ μνμ μ€μ λλ€.
- ν₯μλ μ½λ κ°λ μ±: ν νλ¦Ώ 리ν°λ΄ νμ μ λ¬Έμμ΄μ μμ νμμ λͺ ννκ² νννμ¬ μ½λμ κ°λ μ±μ λμ λλ€.
- ν₯μλ μ μ§λ³΄μμ±: ν νλ¦Ώ 리ν°λ΄ νμ μ λ¬Έμμ΄ μ ν¨μ± κ²μ¬ κ·μΉμ λν λ¨μΌ μ§μ€ 곡κΈμμ μ 곡νμ¬ μ½λμ μ μ§λ³΄μμ±μ λμ λλ€.
- λ λμ κ°λ°μ κ²½ν: ν νλ¦Ώ 리ν°λ΄ νμ μ λ λμ μλ μμ± λ° μ€λ₯ λ©μμ§λ₯Ό μ 곡νμ¬ μ λ°μ μΈ κ°λ°μ κ²½νμ ν₯μμν΅λλ€.
μ ν μ¬ν
ν νλ¦Ώ 리ν°λ΄ νμ μ κ°λ ₯νμ§λ§, λͺ κ°μ§ μ ν μ¬νλ μμ΅λλ€:
- 볡μ‘μ±: ν νλ¦Ώ 리ν°λ΄ νμ μ νΉν 볡μ‘ν ν¨ν΄μ λ€λ£° λ 볡μ‘ν΄μ§ μ μμ΅λλ€. νμ μμ μ±μ μ΄μ κ³Ό μ½λ μ μ§λ³΄μμ± μ¬μ΄μ κ· νμ λ§μΆλ κ²μ΄ μ€μν©λλ€.
- μ±λ₯: ν νλ¦Ώ 리ν°λ΄ νμ μ νΉν λκ·λͺ¨ νλ‘μ νΈμμ μ»΄νμΌ μ±λ₯μ μν₯μ λ―ΈμΉ μ μμ΅λλ€. μ΄λ TypeScriptκ° λ 볡μ‘ν νμ κ²μ¬λ₯Ό μνν΄μΌ νκΈ° λλ¬Έμ λλ€.
- μ νλ μ κ· ννμ μ§μ: ν νλ¦Ώ 리ν°λ΄ νμ μ ν¨ν΄ λ§€μΉμ νμ©νμ§λ§, μ κ· ννμμ λͺ¨λ κΈ°λ₯μ μ§μνμ§λ μμ΅λλ€. λ§€μ° λ³΅μ‘ν λ¬Έμμ΄ μ ν¨μ± κ²μ¬μ κ²½μ°, μ μ ν μ λ ₯ μ΄κ· μ μν΄ μ΄λ¬ν νμ ꡬμ±κ³Ό ν¨κ» λ°νμ μ κ· ννμμ΄ μ¬μ ν νμν μ μμ΅λλ€.
λͺ¨λ² μ¬λ‘
ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©ν λ μΌλμ λμ΄μΌ ν λͺ κ°μ§ λͺ¨λ² μ¬λ‘κ° μμ΅λλ€:
- κ°λ¨νκ² μμνκΈ°: κ°λ¨ν ν¨ν΄λΆν° μμνμ¬ νμμ λ°λΌ μ μ§μ μΌλ‘ 볡μ‘μ±μ λλ €λκ°μΈμ.
- μ€λͺ μ μΈ μ΄λ¦ μ¬μ©: μ½λ κ°λ μ±μ λμ΄κΈ° μν΄ ν νλ¦Ώ 리ν°λ΄ νμ μ μ€λͺ μ μΈ μ΄λ¦μ μ¬μ©νμΈμ.
- νμ λ¬Έμν: ν νλ¦Ώ 리ν°λ΄ νμ μ λͺ©μ κ³Ό μ¬μ©λ²μ μ€λͺ νκΈ° μν΄ λ¬ΈμννμΈμ.
- μ² μ ν ν μ€νΈ: μμλλ‘ μλνλμ§ νμΈνκΈ° μν΄ ν νλ¦Ώ 리ν°λ΄ νμ μ μ² μ ν ν μ€νΈνμΈμ.
- μ±λ₯ κ³ λ €: ν νλ¦Ώ 리ν°λ΄ νμ μ΄ μ»΄νμΌ μ±λ₯μ λ―ΈμΉλ μν₯μ μΌλμ λκ³ κ·Έμ λ°λΌ μ½λλ₯Ό μ΅μ ννμΈμ.
κ²°λ‘
ν νλ¦Ώ 리ν°λ΄ νμ μ TypeScriptμμ νμ λ 벨μμ κ³ κΈ λ¬Έμμ΄ μ‘°μ, ν¨ν΄ λ§€μΉ λ° μ ν¨μ± κ²μ¬λ₯Ό μνν μ μκ² ν΄μ£Όλ κ°λ ₯ν κΈ°λ₯μ λλ€. ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©νλ©΄ λμ± κ²¬κ³ νκ³ μ μ§λ³΄μνκΈ° μ¬μ°λ©° νμ μμ ν μ ν리μΌμ΄μ μ μμ±ν μ μμ΅λλ€. λͺ κ°μ§ μ ν μ¬νμ΄ μμ§λ§, ν νλ¦Ώ 리ν°λ΄ νμ μ μ¬μ©νλ μ΄μ μ λ¨μ μ μννλ κ²½μ°κ° λ§μΌλ―λ‘ λͺ¨λ TypeScript κ°λ°μμκ² κ·μ€ν λꡬμ λλ€. TypeScript μΈμ΄κ° κ³μ λ°μ ν¨μ λ°λΌ μ΄λ¬ν κ³ κΈ νμ κΈ°λ₯μ μ΄ν΄νκ³ νμ©νλ κ²μ κ³ νμ§ μννΈμ¨μ΄λ₯Ό ꡬμΆνλ λ° μ€μν κ²μ λλ€. 볡μ‘μ±κ³Ό κ°λ μ± μ¬μ΄μ κ· νμ μ μ§νκ³ νμ μ² μ ν ν μ€νΈλ₯Ό μ°μ μνλ κ²μ μμ§ λ§μΈμ.