ê³ êž ì¡°ê±Žë¶ ë° ë§€íë íì ì ì¬ì©íì¬ TypeScriptì ê°ë ¥í êž°ë¥ì íì©íìžì. ë³µì¡í ë°ìŽí° 구조ì ì ìíë ì ì°íê³ íì ìì í ì í늬ìŒìŽì ì ë§ëë ë°©ë²ì ë°°ì°ìžì. ì§ì í ëì TypeScript ìœë ìì± êž°ì ì ë§ì€í°íìžì.
ê³ êž TypeScript íšíŽ: ì¡°ê±Žë¶ ë° ë§€íë íì ë§ì€í°
TypeScriptì ê°ì ì ê°ë ¥í íìŽíì ì ê³µíì¬ ì€ë¥ë¥Œ ì¡°êž°ì ê°ì§íê³ ì ì§ êŽëŠ¬ê° ì©ìŽí ìœë륌 ìì±í ì ìë€ë ê²ì
ëë€. string
, number
ë° boolean
곌 ê°ì Ʞ볞 íì
ìŽ êž°ë³žìŽì§ë§, ì¡°ê±Žë¶ ë° ë§€íë íì
곌 ê°ì TypeScriptì ê³ êž êž°ë¥ì ì ì°ì±ê³Œ íì
ìì ì±ì ìë¡ìŽ ì°šìì ìŽìŽì€ëë€. ìŽ í¬êŽì ìž ê°ìŽëë ìŽë¬í ê°ë ¥í ê°ë
ì ììží ìŽíŽë³Žê³ ì§ì ìŒë¡ ëì ìŽê³ ì ì ê°ë¥í TypeScript ì í늬ìŒìŽì
ì ë§ë€ ì ìë ì§ìì ì ê³µí©ëë€.
ì¡°ê±Žë¶ íì ìŽë 묎ìì ëê¹?
ì¡°ê±Žë¶ íì
ì ì¬ì©í멎 JavaScriptì ìŒí ì°ì°ì(condition ? trueValue : falseValue
)ì ì ì¬íê² ì¡°ê±Žì ë°ëŒ ë¬ëŒì§ë íì
ì ì ìí ì ììµëë€. ìŽë¥Œ íµíŽ íì
ìŽ í¹ì ì ìœ ì¡°ê±Žì 충족íëì§ ì¬ë¶ì ë°ëŒ ë³µì¡í íì
êŽê³ë¥Œ ííí ì ììµëë€.
구묞
ì¡°ê±Žë¶ íì ì Ʞ볞 구묞ì ë€ì곌 ê°ìµëë€.
T extends U ? X : Y
T
: íìž ì€ìž íì ì ëë€.U
: ë¹êµí íì ì ëë€.extends
: ìëžíì êŽê³ë¥Œ ëíëŽë í€ìëì ëë€.X
:T
ê°U
ì í ë¹ ê°ë¥í ê²œì° ì¬ì©í íì ì ëë€.Y
:T
ê°U
ì í ë¹í ì ìë ê²œì° ì¬ì©í íì ì ëë€.
볞ì§ì ìŒë¡ T extends U
ê° trueë¡ íê°ë멎 íì
ì X
ë¡ íìžëê³ , ê·žë ì§ ììŒë©Ž Y
ë¡ íìžë©ëë€.
ì€ì©ì ìž ì
1. íšì ë§€ê°ë³ìì íì ê²°ì
íšì ë§€ê°ë³ìê° ë¬žììŽìžì§ ì«ììžì§ íìžíë íì ì ë§ë€ê³ ì¶ë€ê³ ê°ì íŽ ë³Žê² ìµëë€.
type ParamType<T> = T extends string ? string : number;
function processValue(value: ParamType<string | number>): void {
if (typeof value === "string") {
console.log("Value is a string:", value);
} else {
console.log("Value is a number:", value);
}
}
processValue("hello"); // Output: Value is a string: hello
processValue(123); // Output: Value is a number: 123
ìŽ ììì ParamType<T>
ë ì¡°ê±Žë¶ íì
ì
ëë€. T
ê° ë¬žììŽìŽë©Ž íì
ì string
ìŒë¡ íìžëê³ , ê·žë ì§ ììŒë©Ž number
ë¡ íìžë©ëë€. processValue
íšìë ìŽ ì¡°ê±Žë¶ íì
ì ë°ëŒ 묞ììŽ ëë ì«ì륌 íì©í©ëë€.
2. ì ë ¥ íì ì ë°ë¥ž ë°í íì ì¶ì¶
ì ë ¥ì ë°ëŒ ë€ë¥ž íì ì ë°ííë íšìê° ìë ìë늬ì€ë¥Œ ììíŽ ë³Žììì€. ì¡°ê±Žë¶ íì ì ì¬ë°ë¥ž ë°í íì ì ì ìíë ë° ëììŽ ë ì ììµëë€.
interface StringProcessor {
process(input: string): number;
}
interface NumberProcessor {
process(input: number): string;
}
type Processor<T> = T extends string ? StringProcessor : NumberProcessor;
function createProcessor<T extends string | number>(input: T): Processor<T> {
if (typeof input === "string") {
return { process: (input: string) => input.length } as Processor<T>;
} else {
return { process: (input: number) => input.toString() } as Processor<T>;
}
}
const stringProcessor = createProcessor("example");
const numberProcessor = createProcessor(42);
console.log(stringProcessor.process("example")); // Output: 7
console.log(numberProcessor.process(42)); // Output: "42"
ì¬êž°ìì Processor<T>
íì
ì ì
ë ¥ íì
ì ë°ëŒ StringProcessor
ëë NumberProcessor
륌 조걎ë¶ë¡ ì íí©ëë€. ìŽë ê² í멎 createProcessor
íšìê° ì¬ë°ë¥ž íì
ì íë¡ìžì ê°ì²Žë¥Œ ë°íí©ëë€.
3. ì°šë³ë ì ëìš
ì¡°ê±Žë¶ íì ì ì°šë³ë ì ëìšìŒë¡ ìì í ë ë§€ì° ê°ë ¥í©ëë€. ì°šë³ë ì ëìšì ê° ë©€ë²ê° ê³µíµì ëšìŒí€ íì ìì±(ì°šë³ì)ì ê°ë ì ëìš íì ì ëë€. ìŽë¥Œ íµíŽ íŽë¹ ìì±ì ê°ì êž°ë°ìŒë¡ íì ì ì¢í ì ììµëë€.
interface Square {
kind: "square";
size: number;
}
interface Circle {
kind: "circle";
radius: number;
}
type Shape = Square | Circle;
type Area<T extends Shape> = T extends { kind: "square" } ? number : string;
function calculateArea(shape: Shape): Area<typeof shape> {
if (shape.kind === "square") {
return shape.size * shape.size;
} else {
return Math.PI * shape.radius * shape.radius;
}
}
const mySquare: Square = { kind: "square", size: 5 };
const myCircle: Circle = { kind: "circle", radius: 3 };
console.log(calculateArea(mySquare)); // Output: 25
console.log(calculateArea(myCircle)); // Output: 28.274333882308138
ìŽ ìì ìì Shape
íì
ì ì°šë³ë ì ëìšì
ëë€. Area<T>
íì
ì ì¡°ê±Žë¶ íì
ì ì¬ì©íì¬ ëíìŽ ì¬ê°íìžì§ ììžì§ íìžíê³ , ì¬ê°íì ê²œì° number
륌 ë°ííê³ ìì ê²œì° string
ì ë°íí©ëë€(ì€ì ìë늬ì€ììë ìŒêŽë ë°í íì
ì ìí ì ìì§ë§, ìŽê²ì ì늬륌 볎ì¬ì€ëë€).
ì¡°ê±Žë¶ íì ì ëí 죌ì ëŽì©
- 조걎ì ë°ëŒ íì ì ì ìí ì ììµëë€.
- ë³µì¡í íì êŽê³ë¥Œ íííì¬ íì ìì ì±ì í¥ììíµëë€.
- íšì ë§€ê°ë³ì, ë°í íì ë° ì°šë³ë ì ëìš ìì ì ì ì©í©ëë€.
ë§€íë íì ìŽë 묎ìì ëê¹?
ë§€íë íì ì ìì±ì ë§€ííì¬ êž°ì¡Ž íì ì ë³ííë ë°©ë²ì ì ê³µí©ëë€. ìŽë¥Œ íµíŽ ë€ë¥ž íì ì ìì±ì êž°ë°ìŒë¡ ì íì ì ë§ë€ê³ ì íì , ìœêž° ì ì©ìŒë¡ ë§ë€ê±°ë íì ì ë³ê²œíë ë± ìì ì ì ì©í ì ììµëë€.
구묞
ë§€íë íì ì ìŒë°ì ìž êµ¬ë¬žì ë€ì곌 ê°ìµëë€.
type NewType<T> = {
[K in keyof T]: ModifiedType;
};
T
: ì ë ¥ íì ì ëë€.keyof T
:T
ì 몚ë ìì± í€ì ì ëìšì ë°ííë íì ì°ì°ìì ëë€.K in keyof T
:keyof T
ì ê° í€ë¥Œ ë°ë³µíì¬ ê° í€ë¥Œ íì ë³ìK
ì í ë¹í©ëë€.ModifiedType
: ê° ìì±ìŽ ë§€íë íì ì ëë€. ì¬êž°ìë ì¡°ê±Žë¶ íì ëë êž°í íì ë³íìŽ í¬íšë ì ììµëë€.
ì€ì©ì ìž ì
1. ìì± ì íì ìŒë¡ ë§ë€êž°
ë§€íë íì ì ì¬ì©íì¬ êž°ì¡Ž íì ì 몚ë ìì±ì ì íì ìŒë¡ ë§ë€ ì ììµëë€.
interface User {
id: number;
name: string;
email: string;
}
type PartialUser = {
[K in keyof User]?: User[K];
};
const partialUser: PartialUser = {
name: "John Doe",
}; // Valid, as 'id' and 'email' are optional
ì¬êž°ìì PartialUser
ë User
ìží°íìŽì€ì í€ë¥Œ ë°ë³µíë ë§€íë íì
ì
ëë€. ê° í€ K
ì ëíŽ ?
ìììŽë¥Œ ì¶ê°íì¬ ìì±ì ì íì ìŒë¡ ë§ëëë€. User[K]
ë User
ìží°íìŽì€ìì ìì± K
ì íì
ì ê²ìí©ëë€.
2. ìì± ìœêž° ì ì©ìŒë¡ ë§ë€êž°
ë§ì°¬ê°ì§ë¡, Ʞ졎 íì ì 몚ë ìì±ì ìœêž° ì ì©ìŒë¡ ë§ë€ ì ììµëë€.
interface Product {
id: number;
name: string;
price: number;
}
type ReadonlyProduct = {
readonly [K in keyof Product]: Product[K];
};
const readonlyProduct: ReadonlyProduct = {
id: 123,
name: "Example Product",
price: 25.00,
};
// readonlyProduct.price = 30.00; // Error: Cannot assign to 'price' because it is a read-only property.
ìŽ ê²œì° ReadonlyProduct
ë Product
ìží°íìŽì€ì ê° ìì±ì readonly
ìììŽë¥Œ ì¶ê°íë ë§€íë íì
ì
ëë€.
3. ìì± íì ë³í
ë§€íë íì ì ì¬ì©íì¬ ìì±ì íì ì ë³íí ìë ììµëë€. ì륌 ë€ìŽ ëªšë 묞ììŽ ìì±ì ì«ìë¡ ë³ííë íì ì ë§ë€ ì ììµëë€.
interface Config {
apiUrl: string;
timeout: string;
maxRetries: number;
}
type NumericConfig = {
[K in keyof Config]: Config[K] extends string ? number : Config[K];
};
const numericConfig: NumericConfig = {
apiUrl: 123, // Must be a number due to the mapping
timeout: 456, // Must be a number due to the mapping
maxRetries: 3,
};
ìŽ ìì ë ë§€íë íì
ëŽìì ì¡°ê±Žë¶ íì
ì ì¬ì©íë ê²ì 볎ì¬ì€ëë€. ê° ìì± K
ì ëíŽ Config[K]
ì íì
ìŽ ë¬žììŽìžì§ íìží©ëë€. ê·žë ë€ë©Ž íì
ì number
ë¡ ë§€íëê³ , ê·žë ì§ ììŒë©Ž ë³ê²œëì§ ìì ìíë¡ ì ì§ë©ëë€.
4. í€ ì¬ë§€í(TypeScript 4.1 ìŽí)
TypeScript 4.1ììë as
í€ìë륌 ì¬ì©íì¬ ë§€íë íì
ëŽìì í€ë¥Œ ë€ì ë§€ííë êž°ë¥ì ëì
íìµëë€. ìŽë¥Œ íµíŽ ìë íì
ì êž°ë°ìŒë¡ ë€ë¥ž ìì± ìŽëŠìŒë¡ ì íì
ì ë§ë€ ì ììµëë€.
interface Event {
eventId: string;
eventName: string;
eventDate: Date;
}
type TransformedEvent = {
[K in keyof Event as `new${Capitalize<string&K>}`]: Event[K];
};
// Result:
// {
// newEventId: string;
// newEventName: string;
// newEventDate: Date;
// }
//Capitalize function used to Capitalize first letter
type Capitalize<S extends string> = Uppercase<string&S> extends never ? string : `$Capitalize<S>`;
//Usage with an actual object
const myEvent: TransformedEvent = {
newEventId: "123",
newEventName: "New Name",
newEventDate: new Date()
};
ì¬êž°ìì TransformedEvent
íì
ì ê° í€ K
륌 "new"ë¡ ììíê³ ë묞ìë¡ ììíë ì í€ë¡ ë€ì ë§€íí©ëë€. `Capitalize` ì ížëŠ¬í° íšìë í€ì 첫 êžìê° ë묞ììžì§ íìží©ëë€. `string & K` êµì°šë ì°ëŠ¬ê° ë¬žììŽ í€ë§ ì²ëЬíê³ Kìì ì¬ë°ë¥ž 늬í°ëŽ ì íì ê°ì žì€ëì§ íìží©ëë€.
í€ ì¬ë§€íì í¹ì ì구 ì¬íì ë°ëŒ íì
ì ë³ííê³ ì¡°ì íë ê°ë ¥í ê°ë¥ì±ì ìœëë€. ìŽë¥Œ íµíŽ ë³µì¡í ë
ŒëŠ¬ë¥Œ êž°ë°ìŒë¡ í€ì ìŽëŠì ë°êŸžê±°ë, íí°ë§íê±°ë ìì í ì ììµëë€.
ë§€íë íì ì ëí 죌ì ëŽì©
- ìì±ì ë§€ííì¬ êž°ì¡Ž íì ì ë³íí ì ììµëë€.
- ìì±ì ì íì ìŒë¡, ìœêž° ì ì©ìŒë¡ ë§ë€ê±°ë íì ì ë³ê²œí ì ììµëë€.
- ë€ë¥ž íì ì ìì±ì êž°ë°ìŒë¡ ì íì ì ë§ëë ë° ì ì©í©ëë€.
- í€ ì¬ë§€í(TypeScript 4.1ì ëì )ì íì ë³íìì ëì± ë°ìŽë ì ì°ì±ì ì ê³µí©ëë€.
ì¡°ê±Žë¶ ë° ë§€íë íì ê²°í©
ì¡°ê±Žë¶ ë° ë§€íë íì ì ì§ì í íì ìŽë€ì ê²°í©í ë ëìµëë€. ìŽë¥Œ íµíŽ êŽë²ìí ìë늬ì€ì ì ìí ì ìë ë§€ì° ì ì°íê³ ííë ¥ìŽ íë¶í íì ì ì륌 ë§ë€ ì ììµëë€.
ì: íì ë³ ìì± íí°ë§
ê°ì²Žì ìì±ì íŽë¹ íì ì êž°ë°ìŒë¡ íí°ë§íë íì ì ë§ë€ê³ ì¶ë€ê³ ê°ì íŽ ë³Žê² ìµëë€. ì륌 ë€ìŽ ê°ì²Žìì 묞ììŽ ìì±ë§ ì¶ì¶í ì ììµëë€.
interface Data {
name: string;
age: number;
city: string;
country: string;
isEmployed: boolean;
}
type StringProperties<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K];
};
type StringData = StringProperties<Data>;
// Result:
// {
// name: string;
// city: string;
// country: string;
// }
const stringData: StringData = {
name: "John",
city: "New York",
country: "USA",
};
ìŽ ììì StringProperties<T>
íì
ì í€ ì¬ë§€í ë° ì¡°ê±Žë¶ íì
ì ì¬ì©íì¬ ë§€íë íì
ì ì¬ì©í©ëë€. ê° ìì± K
ì ëíŽ T[K]
ì íì
ìŽ ë¬žììŽìžì§ íìží©ëë€. ê·žë ë€ë©Ž í€ê° ì ì§ëê³ , ê·žë ì§ ììŒë©Ž never
ë¡ ë§€íëìŽ íšê³Œì ìŒë¡ íí°ë§ë©ëë€. ë§€íë íì
í€ë¡ never
ë 결곌 íì
ìì ì ê±°í©ëë€. ìŽë ê² í멎 묞ììŽ ìì±ë§ StringData
íì
ì í¬íšë©ëë€.
TypeScriptì ì ížëŠ¬í° íì
TypeScriptë ì¡°ê±Žë¶ ë° ë§€íë íì ì íì©íì¬ ìŒë°ì ìž íì ë³íì ìííë ëª ê°ì§ Ʞ볞 ì ê³µ ì ížëŠ¬í° íì ì ì ê³µí©ëë€. ìŽë¬í ì ížëŠ¬í° íì ì ìŽíŽí멎 ìœë륌 í¬ê² ëšìííê³ íì ìì ì±ì í¥ììí¬ ì ììµëë€.
ìŒë°ì ìž ì ížëŠ¬í° íì
Partial<T>
:T
ì 몚ë ìì±ì ì íì ìŒë¡ ë§ëëë€.Readonly<T>
:T
ì 몚ë ìì±ì ìœêž° ì ì©ìŒë¡ ë§ëëë€.Required<T>
:T
ì 몚ë ìì±ì íì í목ìŒë¡ ë§ëëë€(?
ìììŽ ì ê±°).Pick<T, K extends keyof T>
:T
ìì ìì± ì§í©K
륌 ì íí©ëë€.Omit<T, K extends keyof T>
:T
ìì ìì± ì§í©K
륌 ì ê±°í©ëë€.Record<K extends keyof any, T>
: íìT
ì ìì± ì§í©K
ë¡ íì ì 구ì±í©ëë€.Exclude<T, U>
:U
ì í ë¹ ê°ë¥í 몚ë íì ìT
ìì ì ìží©ëë€.Extract<T, U>
:U
ì í ë¹ ê°ë¥í 몚ë íì ìT
ìì ì¶ì¶í©ëë€.NonNullable<T>
:null
ë°undefined
륌T
ìì ì ìží©ëë€.Parameters<T>
: ííìì íšì íìT
ì ë§€ê°ë³ì륌 ê°ì žìµëë€.ReturnType<T>
: íšì íìT
ì ë°í íì ì ê°ì žìµëë€.InstanceType<T>
: ìì±ì íšì íìT
ì ìžì€íŽì€ íì ì ê°ì žìµëë€.ThisType<T>
: 컚í ì€ížthis
íì ì ë§ì»€ ìí ì í©ëë€.
ìŽë¬í ì ížëŠ¬í° íì
ì ì¡°ê±Žë¶ ë° ë§€íë íì
ì ì¬ì©íì¬ êµ¬ì¶ëììŒë©°, ìŽë¬í ê³ êž TypeScript êž°ë¥ì ê°ë ¥íšê³Œ ì ì°ì±ì 볎ì¬ì€ëë€. ì륌 ë€ìŽ Partial<T>
ë ë€ì곌 ê°ìŽ ì ìë©ëë€.
type Partial<T> = {
[P in keyof T]?: T[P];
};
ì¡°ê±Žë¶ ë° ë§€íë íì ì¬ì©ì ìí ëªšë² ì¬ë¡
ì¡°ê±Žë¶ ë° ë§€íë íì ì ê°ë ¥íì§ë§, ì ì€íê² ì¬ì©íì§ ììŒë©Ž ìœë륌 ë ë³µì¡íê² ë§ë€ ìë ììµëë€. ë€ìì ìŒëì ëìŽìŒ í ëª ê°ì§ ëªšë² ì¬ë¡ì ëë€.
- ëšìíê² ì ì§: ì§ëì¹ê² ë³µì¡í ì¡°ê±Žë¶ ë° ë§€íë íì ì ì¬ì©íì§ ë§ììì€. íì ì ìê° ë묎 ë³µì¡íŽì§ë©Ž ë ìê³ êŽëЬíêž° ì¬ìŽ ë¶ë¶ìŒë¡ ëëë ê²ì ê³ ë €íììì€.
- ì믞 ìë ìŽëŠ ì¬ì©: ì¡°ê±Žë¶ ë° ë§€íë íì ì 목ì ì ëª ííê² ëíëŽë ì€ëª ì ìž ìŽëŠì ì§ì í©ëë€.
- íì 묞ìí: í¹í ë³µì¡í ê²œì° ì¡°ê±Žë¶ ë° ë§€íë íì ë€ì ìë ë ŒëŠ¬ë¥Œ ì€ëª íë 죌ìì ì¶ê°íììì€.
- ì ížëŠ¬í° íì íì©: ì¬ì©ì ì§ì ì¡°ê±Žë¶ ëë ë§€íë íì ì ë§ë€êž° ì ì ëŽì¥ ì ížëŠ¬í° íì ìŽ ëìŒí 결곌륌 ì»ì ì ìëì§ íìží©ëë€.
- íì í ì€íž: ë€ìí ìë늬ì€ë¥Œ ë€ë£šë ëšì í ì€ížë¥Œ ìì±íì¬ ì¡°ê±Žë¶ ë° ë§€íë íì ìŽ ììëë¡ ìëíëì§ íìžíììì€.
- ì±ë¥ ê³ ë €: ë³µì¡í íì ê³ì°ì 컎íìŒ ìê°ì ìí¥ì ë¯žì¹ ì ììµëë€. íì ì ìì ì±ë¥ ìí¥ì ìŒëì ëììì€.
ê²°ë¡
ì¡°ê±Žë¶ ë° ë§€íë íì ì TypeScript륌 ë§ì€í°íêž° ìí íì ë구ì ëë€. ìŽë¥Œ íµíŽ ë³µì¡í ë°ìŽí° 구조 ë° ëì ì구 ì¬íì ì ìíë ë§€ì° ì ì°íê³ íì ìì íë©° ì ì§ êŽëŠ¬ê° ì©ìŽí ì í늬ìŒìŽì ì ë§ë€ ì ììµëë€. ìŽ ê°ìŽëìì ë Œìë ê°ë ì ìŽíŽíê³ ì ì©íšìŒë¡ìš TypeScriptì 몚ë ì ì¬ë ¥ì íì©íê³ ë³Žë€ ê°ë ¥íê³ íì¥ ê°ë¥í ìœë륌 ìì±í ì ììµëë€. TypeScript륌 ê³ì í구í멎ì, ëì ì ìž íìŽí 묞ì 륌 íŽê²°í ì ìë ìë¡ìŽ ë°©ë²ì ì°Ÿêž° ìíŽ ì¡°ê±Žë¶ ë° ë§€íë íì ì ë€ìí ì¡°í©ì ì€ííë ê²ì ìì§ ë§ììì€. ê°ë¥ì±ì ì ë§ ë¬Žê¶ë¬Žì§í©ëë€.