í í늿 늬í°ëŽ íì 곌 ì¡°ê±Žë¶ íì 곌 ê°ì TypeScript ê³ êž êž°ë¥ì íìíì¬ ë ííë ¥ìŽ íë¶íê³ ì ì§ êŽëŠ¬ê° ì©ìŽí ìœë륌 ìì±íìžì. ë³µì¡í ìë늬ì€ë¥Œ ìí íì ì¡°ìì ë§ì€í°íìžì.
TypeScript ê³ êž íì : í í늿 늬í°ëŽ ë° ì¡°ê±Žë¶ íì ë§ì€í°íêž°
TypeScriptì ê°ì ì ê°ë ¥í íì
ìì€í
ì ììµëë€. string, number, boolean곌 ê°ì Ʞ볞 íì
ì ë§ì ìë늬ì€ì ì¶©ë¶íì§ë§, í
í늿 늬í°ëŽ íì
곌 ì¡°ê±Žë¶ íì
곌 ê°ì ê³ êž êž°ë¥ì ìë¡ìŽ ìì€ì ííë ¥ê³Œ íì
ìì ì±ì ì ê³µí©ëë€. ìŽ ê°ìŽëë ìŽë¬í ê³ êž íì
ì ëí í¬êŽì ìž ê°ì륌 ì ê³µíê³ , êž°ë¥ì í구íê³ ì€ì©ì ìž ìì© íë¡ê·žëšì ìì°í©ëë€.
í í늿 늬í°ëŽ íì ìŽíŽíêž°
í í늿 늬í°ëŽ íì ì JavaScriptì í í늿 늬í°ëŽì êž°ë°ìŒë¡ íë©°, 묞ììŽ ë³Žê°ì êž°ë°ìŒë¡ íì ì ì ìí ì ììµëë€. ìŽë¥Œ íµíŽ í¹ì 묞ììŽ íšíŽì ëíëŽë íì ì ìì±íì¬ ìœë륌 ëì± ê²¬ê³ íê³ ììž¡ ê°ë¥íê² ë§ë€ ì ììµëë€.
Ʞ볞 구묞 ë° ì¬ì©ë²
í
í늿 늬í°ëŽ íì
ì JavaScript í
í늿 늬í°ëŽê³Œ ì ì¬íê² ë°±í±(`)ì ì¬ì©íì¬ íì
ì ì륌 묶ìµëë€. ë°±í± ëŽìì ${} 구묞ì ì¬ì©íì¬ ë€ë¥ž íì
ì 볎ê°í ì ììµëë€. ì¬êž°ì ë§ë²ìŽ ìŒìŽë©ëë€. 볞ì§ì ìŒë¡, 컎íìŒ íìì ë³Žê° ëŽì íì
ì êž°ë°ìŒë¡ 구ì±ë 묞ììŽ íì
ìŽ ìì±ë©ëë€.
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type APIEndpoint = `/api/${string}`;
// ìì ì¬ì©ë²
const getEndpoint: APIEndpoint = "/api/users"; // ì íš
const postEndpoint: APIEndpoint = "/api/products/123"; // ì íš
const invalidEndpoint: APIEndpoint = "/admin/settings"; // TypeScriptë `string`ìŽ ë¬ŽììŽë ë ì ììŒë¯ë¡ ì¬êž°ì ì€ë¥ë¥Œ íìíì§ ììµëë€.
ìŽ ììì APIEndpointë /api/ë¡ ììíë 몚ë 묞ììŽì ëíëŽë íì
ì
ëë€. ìŽ êž°ë³ž ìì ê° ì ì©íì§ë§, í
í늿 늬í°ëŽ íì
ì ì§ì í íì ë 구첎ì ìž íì
ì ìœ ì¡°ê±Žê³Œ ê²°í©ë ë ëíë©ëë€.
ì ëìš íì 곌 ê²°í©
í í늿 늬í°ëŽ íì ì ì ëìš íì 곌 íšê» ì¬ì©ë ë ì§ì ìŒë¡ ë¹ì ë°í©ëë€. ìŽë¥Œ íµíŽ í¹ì 묞ììŽ ì¡°í© ì§í©ì ëíëŽë íì ì ë§ë€ ì ììµëë€.
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type APIPath = "users" | "products" | "orders";
type APIEndpoint = `/${APIPath}/${HTTPMethod}`;
// ì íší API ìëí¬ìžíž
const getUsers: APIEndpoint = "/users/GET";
const postProducts: APIEndpoint = "/products/POST";
// ì íšíì§ ìì API ìëí¬ìžíž (TypeScript ì€ë¥ ë°ì)
// const invalidEndpoint: APIEndpoint = "/users/PATCH"; // ì€ë¥: "/users/PATCH"ë íì
"/users/GET" | "/users/POST" | ... 3ê° ë ... | "/orders/DELETE"ì í ë¹í ì ììµëë€.
ìŽì APIEndpointë API 겜ë¡ì HTTP ë©ìëì í¹ì ì¡°í©ë§ íì©íë ë ì íì ìž íì
ì
ëë€. TypeScriptë ì못ë ì¡°í©ì ì¬ì©íë €ë ìë륌 íëê·ž íìíì¬ íì
ìì ì±ì í¥ììíµëë€.
í í늿 늬í°ëŽ íì ì ì¬ì©í 묞ììŽ ì¡°ì
TypeScriptë í í늿 늬í°ëŽ íì 곌 ì벜íê² ìëíë ëŽì¥ 묞ììŽ ì¡°ì íì ì ì ê³µí©ëë€. ìŽë¬í íì ì ì¬ì©í멎 컎íìŒ íìì 묞ììŽì ë³íí ì ììµëë€.
- Uppercase: 묞ììŽì ë묞ìë¡ ë³íí©ëë€.
- Lowercase: 묞ììŽì ì묞ìë¡ ë³íí©ëë€.
- Capitalize: 묞ììŽì 첫 êžì륌 ë묞ìë¡ ë§ëëë€.
- Uncapitalize: 묞ììŽì 첫 êžì륌 ì묞ìë¡ ë§ëëë€.
type Greeting = "hello world";
type UppercaseGreeting = Uppercase; // "HELLO WORLD"
type LowercaseGreeting = Lowercase; // "hello world"
type CapitalizedGreeting = Capitalize; // "Hello world"
type UncapitalizedGreeting = Uncapitalize; // "hello world"
ìŽë¬í 묞ììŽ ì¡°ì íì ì ëª ëª ê·ì¹ì êž°ë°ìŒë¡ ìëìŒë¡ íì ì ìì±íë ë° í¹í ì ì©í©ëë€. ì륌 ë€ìŽ, ìŽë²€íž ìŽëŠìì ì¡ì íì ì íìíê±°ë ê·ž ë°ëë¡ í ì ììµëë€.
í í늿 늬í°ëŽ íì ì ì€ì©ì ìž ìì©
- API ìëí¬ìžíž ì ì: ììì ì€ëª í ê²ì²ëŒ, ì íí íì ì ìœ ì¡°ê±ŽìŒë¡ API ìëí¬ìžížë¥Œ ì ìí©ëë€.
- ìŽë²€íž ì²ëЬ: í¹ì ì ëì¬ ë° ì 믞ì¬ê° ìë ìŽë²€íž ìŽëŠì ëí íì ìì±.
- CSS íŽëì€ ìì±: êµ¬ì± ìì ìŽëŠ ë° ìí륌 êž°ë°ìŒë¡ CSS íŽëì€ ìŽëŠ ìì±.
- ë°ìŽí°ë² ìŽì€ 쿌늬 ë¹ë©: ë°ìŽí°ë² ìŽì€ 쿌늬륌 구ì±í ë íì ìì ì± ë³Žì¥.
êµì ìì: íµí íì ì§ì
ì¬ë¬ íµí륌 ì§ìíë êžìµ ì í늬ìŒìŽì ì 구ì¶íë€ê³ ììíŽ ë³Žìžì. í í늿 늬í°ëŽ íì ì ì¬ì©íì¬ ì¬ë°ë¥ž íµí íìì ì ì©í ì ììµëë€.
type CurrencyCode = "USD" | "EUR" | "GBP" | "JPY";
type CurrencyFormat = `${number} ${T}`;
const priceUSD: CurrencyFormat<"USD"> = "100 USD"; // ì íš
const priceEUR: CurrencyFormat<"EUR"> = "50 EUR"; // ì íš
// const priceInvalid: CurrencyFormat<"USD"> = "100 EUR"; // ì€ë¥: íì
'string'ì íì
'`${number} USD`'ì í ë¹í ì ììµëë€.
function formatCurrency(amount: number, currency: T): CurrencyFormat {
return `${amount} ${currency}`;
}
const formattedUSD = formatCurrency(250, "USD"); // íì
: "250 USD"
const formattedEUR = formatCurrency(100, "EUR"); // íì
: "100 EUR"
ìŽ ìì ë íµí ê°ìŽ íì ì¬ë°ë¥ž íµí ìœëë¡ íììŽ ì§ì ëëë¡ íì¬ ì ì¬ì ìž ì€ë¥ë¥Œ ë°©ì§í©ëë€.
ì¡°ê±Žë¶ íì í구
ì¡°ê±Žë¶ íì ì TypeScriptì íì ìì€í ì ë¶êž° ë¡ì§ì ëì íì¬ ë€ë¥ž íì ì ì졎íë íì ì ì ìí ì ììµëë€. ìŽ êž°ë¥ì ë§€ì° ì ì°íê³ ì¬ì¬ì© ê°ë¥í íì ì ì륌 ë§ëë ë° ë§€ì° ê°ë ¥í©ëë€.
Ʞ볞 구묞 ë° ì¬ì©ë²
ì¡°ê±Žë¶ íì
ì infer í€ìëì ìŒí ì°ì°ì(condition ? trueType : falseType)륌 ì¬ì©íì¬ íì
조걎ì ì ìí©ëë€.
type IsString = T extends string ? true : false;
type StringCheck = IsString; // type StringCheck = true
type NumberCheck = IsString; // type NumberCheck = false
ìŽ ììì IsStringë Tê° stringì í ë¹ ê°ë¥íì§ íìžíë ì¡°ê±Žë¶ íì
ì
ëë€. ê·žë ë€ë©Ž íì
ì trueë¡, ê·žë ì§ ììŒë©Ž falseë¡ ê²°ì ë©ëë€.
infer í€ìë
infer í€ìë륌 ì¬ì©í멎 íì
ìì íì
ì ì¶ì¶í ì ììµëë€. ìŽë íšì íì
ëë ë°°ìŽ íì
곌 ê°ì ë³µì¡í íì
ìŒë¡ ìì
í ë í¹í ì ì©í©ëë€.
type ReturnType any> = T extends (...args: any) => infer R ? R : any;
function add(a: number, b: number): number {
return a + b;
}
type AddReturnType = ReturnType; // type AddReturnType = number
ìŽ ììì ReturnTypeë íšì íì
Tì ë°í íì
ì ì¶ì¶í©ëë€. ì¡°ê±Žë¶ íì
ì infer R ë¶ë¶ì ë°í íì
ì ì¶ë¡ íì¬ íì
ë³ì Rì í ë¹í©ëë€. Tê° íšì íì
ìŽ ìë멎 íì
ì anyë¡ ê²°ì ë©ëë€.
ë¶ì° ì¡°ê±Žë¶ íì
íìžë íì ìŽ ë€ìŽí€ë íì ë§€ê°ë³ììž ê²œì° ì¡°ê±Žë¶ íì ì ë¶ì°ë©ëë€. ìŠ, ì¡°ê±Žë¶ íì ì ì ëìš íì ì ê° ë©€ë²ì ê°ë³ì ìŒë¡ ì ì©ë©ëë€.
type ToArray = T extends any ? T[] : never;
type NumberOrStringArray = ToArray; // type NumberOrStringArray = string[] | number[]
ìŽ ììì ToArrayë íì
T륌 ë°°ìŽ íì
ìŒë¡ ë³íí©ëë€. Tê° ë€ìŽí€ë íì
ë§€ê°ë³ì(ë€ë¥ž íì
ìŒë¡ ëíëì§ ìì)ìŽë¯ë¡ ì¡°ê±Žë¶ íì
ì numberì stringì ê°ë³ì ìŒë¡ ì ì©ëìŽ number[]ì string[]ì ì ëìšìŽ ìì±ë©ëë€.
ì¡°ê±Žë¶ íì ì ì€ì©ì ìž ìì©
- ë°í íì ì¶ì¶: ììì ì€ëª í ê²ì²ëŒ íšìì ë°í íì ì ì¶ì¶í©ëë€.
- ì ëìšìì íì íí°ë§: ì ëìšìì í¹ì íì ë§ í¬íšíë íì ìì±.
- ì€ë²ë¡ëë íšì íì ì ì: ì ë ¥ íì ì ë°ëŒ ë€ë¥ž íšì íì ìì±.
- íì ê°ë ìì±: ë³ìì íì ì ì¢íë íšì ì ì.
êµì ìì: ë€ìí ë ì§ íì ì²ëЬ
ìžê³ì ë€ë¥ž ì§ìììë ë€ë¥ž ë ì§ íìì ì¬ì©í©ëë€. ì¡°ê±Žë¶ íì ì ì¬ì©íì¬ ìŽë¬í ë³íì ì²ëЬí ì ììµëë€.
type DateFormat = "YYYY-MM-DD" | "MM/DD/YYYY" | "DD.MM.YYYY";
type ParseDate = T extends "YYYY-MM-DD"
? { year: number; month: number; day: number; format: "YYYY-MM-DD" }
: T extends "MM/DD/YYYY"
? { month: number; day: number; year: number; format: "MM/DD/YYYY" }
: T extends "DD.MM.YYYY"
? { day: number; month: number; year: number; format: "DD.MM.YYYY" }
: never;
function parseDate(dateString: string, format: T): ParseDate {
// (구íì ë€ë¥ž ë ì§ íìì ì²ëЬí©ëë€)
if (format === "YYYY-MM-DD") {
const [year, month, day] = dateString.split("-").map(Number);
return { year, month, day, format } as ParseDate;
} else if (format === "MM/DD/YYYY") {
const [month, day, year] = dateString.split("/").map(Number);
return { month, day, year, format } as ParseDate;
} else if (format === "DD.MM.YYYY") {
const [day, month, year] = dateString.split(".").map(Number);
return { day, month, year, format } as ParseDate;
} else {
throw new Error("ì못ë ë ì§ íì");
}
}
const parsedDateISO = parseDate("2023-10-27", "YYYY-MM-DD"); // íì
: { year: number; month: number; day: number; format: "YYYY-MM-DD"; }
const parsedDateUS = parseDate("10/27/2023", "MM/DD/YYYY"); // íì
: { month: number; day: number; year: number; format: "MM/DD/YYYY"; }
const parsedDateEU = parseDate("27.10.2023", "DD.MM.YYYY"); // íì
: { day: number; month: number; year: number; format: "DD.MM.YYYY"; }
console.log(parsedDateISO.year); // ê±°êž°ì ìì ê²ìŽëŒë ê²ì ìê³ ì°ëì ì¡ìžì€
ìŽ ìì ë ì¡°ê±Žë¶ íì
ì ì¬ì©íì¬ ì§ì ë ë ì§ íìì êž°ë°ìŒë¡ ë€ë¥ž ë ì§ êµ¬ë¬ž ë¶ì íšì륌 ì ìí©ëë€. ParseDate íì
ì ë°íë ê°ì²Žê° íìì ë°ëŒ ì¬ë°ë¥ž ìì±ì ê°ëë¡ í©ëë€.
í í늿 늬í°ëŽê³Œ ì¡°ê±Žë¶ íì ê²°í©
ì§ì í íì í í늿 늬í°ëŽ íì 곌 ì¡°ê±Žë¶ íì ì ê²°í©í ë ëíë©ëë€. ìŽë¥Œ íµíŽ ë§€ì° ê°ë ¥í íì ì¡°ììŽ ê°ë¥í©ëë€.
type EventName = `on${Capitalize}`;
type ExtractEventPayload = T extends EventName
? { type: T; payload: any } // ìì°ì© ëšìí
: never;
type ClickEvent = EventName<"click">; // "onClick"
type MouseOverEvent = EventName<"mouseOver">; // "onMouseOver"
// íì
ì ì¬ì©íë ìì íšì
function processEvent(event: T): ExtractEventPayload {
// ì€ì 구íììë ì€ì ë¡ ìŽë²€ížë¥Œ 볎ë
ëë€.
console.log(`ìŽë²€íž ì²ëЬ ${event}`);
// ì€ì 구íììë íìŽë¡ëê° ìŽë²€íž íì
ì êž°ë°ìŒë¡ í©ëë€.
return { type: event, payload: {} } as ExtractEventPayload;
}
// ë°í íì
ìŽ ë§€ì° êµ¬ì²Žì ì
ëë€:
const clickEvent = processEvent("onClick"); // { type: "onClick"; payload: any; }
const mouseOverEvent = processEvent("onMouseOver"); // { type: "onMouseOver"; payload: any; }
// ë€ë¥ž 묞ììŽì ì¬ì©í멎 neverê° íìë©ëë€.
// const someOtherEvent = processEvent("someOtherEvent"); // íì
ì `never`ì
ëë€.
ëªšë² ì¬ë¡ ë° ê³ ë € ì¬í
- ëšìíê² ì ì§: ê°ë ¥íì§ë§ ìŽë¬í ê³ êž íì ì ë¹ ë¥Žê² ë³µì¡íŽì§ ì ììµëë€. ëª íì±ê³Œ ì ì§ êŽëЬì±ì ìíŽ ë žë ¥íììì€.
- ì² ì íê² í ì€íž: í¬êŽì ìž ëšì í ì€ížë¥Œ ìì±íì¬ íì ì ìê° ììëë¡ ìëíëì§ íìží©ëë€.
- ìœë 묞ìí: ìœë ê°ë ì±ì í¥ììí€êž° ìíŽ ê³ êž íì ì 목ì 곌 ëìì ëª ííê² ë¬žìíí©ëë€.
- ì±ë¥ ê³ ë €: ê³ êž íì ì 곌ëíê² ì¬ì©í멎 컎íìŒ ìê°ì ìí¥ì ë¯žì¹ ì ììµëë€. ìœë륌 íë¡íìŒë§íê³ íìí ê²œì° ìµì íí©ëë€.
ê²°ë¡
í í늿 늬í°ëŽ íì 곌 ì¡°ê±Žë¶ íì ì TypeScriptì ê°ë ¥í ë구ì ëë€. ìŽë¬í ê³ êž íì ì ë§ì€í°í멎 ë ííë ¥ìŽ íë¶íê³ , ì ì§ êŽëŠ¬ê° ì©ìŽíë©°, íì ìì í ìœë륌 ìì±í ì ììµëë€. ìŽë¬í êž°ë¥ì íµíŽ íì ê°ì ë³µì¡í êŽê³ë¥Œ 캡ì²íê³ , ë ì격í ì ìœ ì¡°ê±Žì ì ì©íê³ , ì¬ì¬ì© ê°ë¥í íì ì ì륌 ë§ë€ ì ììµëë€. ìŽë¬í êž°ì ì íì©íì¬ TypeScript êž°ì ì í¥ììí€ê³ ì ìžê³ ì¬ì©ì륌 ìí ê°ë ¥íê³ íì¥ ê°ë¥í ì í늬ìŒìŽì ì 구ì¶íììì€.