ëì ê°ì²Ž ë³í곌 ì ì°í ìì± ìì ì ìí TypeScript ë§€íë íì ì ê°ë ¥í êž°ë¥ì íì©íì¬, ì ìžê³ ê°ë°ìë€ì ìí ìœë ì¬ì¬ì©ì±ê³Œ íì ìì ì±ì í¥ììí€ìžì.
TypeScript ë§€íë íì : ê°ì²Ž ë³í ë° ìì± ìì ë§ì€í°íêž°
ëìììŽ ì§ííë ìíížìšìŽ ê°ë° í겜ìì, ì ì§ ë³Žì ê°ë¥íê³ íì¥ ê°ë¥íë©° ì 뢰í ì ìë ì í늬ìŒìŽì ì 구ì¶íêž° ìíŽìë ê°ë ¥í íì ìì€í ìŽ íìì ì ëë€. TypeScriptë ê°ë ¥í íì ì¶ë¡ ë° ê³ êž êž°ë¥ ëë¶ì ì ìžê³ ê°ë°ìë€ìê² ììŽìë ì ë ëêµ¬ê° ëììµëë€. ê·žì€ ê°ì¥ ê°ë ¥í êž°ë¥ ì€ íëë Ʞ졎 ê°ì²Ž íì ì ìë¡ìŽ íì ìŒë¡ ë³íí ì ìê² íŽì£Œë ì êµí ë©ì»€ëìŠìž ë§€íë íì (Mapped Types)ì ëë€. ìŽ ëžë¡ê·ž ê²ì묌ììë TypeScript ë§€íë íì ì ìžê³ë¥Œ ê¹ìŽ í구íë©°, ê·ž Ʞ볞ì ìž ê°ë , ì€ì ì ì© ì¬ë¡, ê·žëŠ¬ê³ ê°ë°ìê° ê°ì²Ž ë³í ë° ìì± ìì ì ì°ìíê² ì²ëЬí ì ìëë¡ ëë ë°©ë²ì ìŽíŽë³Žê² ìµëë€.
ë§€íë íì ì íµì¬ ê°ë ìŽíŽíêž°
볞ì§ì ìŒë¡ ë§€íë íì ì Ʞ졎 íì ì ìì±ë€ì ë°ë³µíì¬ ìë¡ìŽ íì ì ìì±íë ë°©ë²ì ëë€. ìŽë¥Œ íì ì ëí 룚íëŒê³ ìê°íŽë³Žìžì. ì볞 íì ì ê° ìì±ì ëíŽ í€, ê° ëë ë ë€ì ë³íì ì ì©í ì ììµëë€. ìŽë ìëì ìž ë°ë³µ ììŽ êž°ì¡Ž íì ì ì륌 êž°ë°ìŒë¡ ìë¡ìŽ íì ì ì륌 ìì±í ì ìë ë°©ëí ê°ë¥ì±ì ìŽìŽì€ëë€.
ë§€íë íì
ì Ʞ볞 묞ë²ì { [P in K]: T } 구조륌 í¬íšíë©°, ì¬êž°ì:
P: ë°ë³µëë ìì±ì ìŽëŠì ëíë ëë€.in K: ìŽ ë¶ë¶ìŽ íµì¬ì ëë€.Pê° íìK(ìŒë°ì ìŒë¡ 묞ììŽ ëŠ¬í°ëŽì ì ëìš ëë keyof íì )ìì ê° í€ë¥Œ ì·ší ê²ìì ëíë ëë€.T: ì íì ìì ìì±Pì ê° íì ì ì ìí©ëë€.
ê°ëší ììë¶í° ììíŽëŽ ìë€. ì¬ì©ì ë°ìŽí°ë¥Œ ëíëŽë ê°ì²Žê° ìê³ , 몚ë ìì±ìŽ ì íì ìž ìë¡ìŽ íì ì ë§ë€ê³ ì¶ë€ê³ ììíŽ ë³Žìžì. ìŽë ì륌 ë€ìŽ ì€ì ê°ì²Žë¥Œ 구ì¶íê±°ë ë¶ë¶ ì ë°ìŽížë¥Œ 구íí ë íí ë°ìíë ìë늬ì€ì ëë€.
ìì 1: 몚ë ìì±ì ì íì ìŒë¡ ë§ë€êž°
ìŽ êž°ë³ž íì ì ê³ ë €íŽ ë³Žìžì:
type User = {
id: number;
name: string;
email: string;
isActive: boolean;
};
ë§€íë íì
ì ì¬ì©íì¬ ëªšë ìì±ìŽ ì íì ìž ìë¡ìŽ íì
OptionalUser륌 ë§ë€ ì ììµëë€:
type OptionalUser = {
[P in keyof User]?: User[P];
};
ìŽë¥Œ ë¶ìíŽ ëŽ ìë€:
keyof User: ìŽëUseríì ì í€(ì:'id' | 'name' | 'email' | 'isActive')ë€ì ì ëìšì ìì±í©ëë€.P in keyof User: ìŽë ì ëìšì ê° í€ë¥Œ ë°ë³µí©ëë€.?: ìŽë ìì±ì ì íì ìŒë¡ ë§ëë ìì ìì ëë€.User[P]: ìŽë 룩ì (lookup) íì ì ëë€. ê° í€Pì ëíŽ ì볞Useríì ìì íŽë¹ ê° íì ì ê°ì žìµëë€.
결곌ì ìž OptionalUser íì
ì ë€ì곌 ê°ìŽ ë³ŽìŒ ê²ì
ëë€:
{
id?: number;
name?: string;
email?: string;
isActive?: boolean;
}
ìŽë ìì²ëê² ê°ë ¥í©ëë€. ê° ìì±ì ?ë¡ ìëìŒë¡ ì¬ì ìíë ëì , íì
ì ëì ìŒë¡ ìì±íìµëë€. ìŽ ìì¹ì ë€ë¥ž ë§ì ì ížëŠ¬í° íì
ì ë§ëë ë° íì¥ë ì ììµëë€.
ë§€íë íì ì ìŒë°ì ìž ìì± ìì ì
ë§€íë íì ì ëšìí ìì±ì ì íì ìŒë¡ ë§ëë ê²ë§ìŽ ìëëë€. 결곌 íì ì ìì±ì ë€ìí ìì ì륌 ì ì©í ì ìëë¡ í©ëë€. ê°ì¥ ìŒë°ì ìž ê²ë€ì ë€ì곌 ê°ìµëë€:
- ì íì±(Optionality):
?ìì ì륌 ì¶ê°íê±°ë ì ê±°í©ëë€. - ìœêž° ì ì©(Readonly):
readonlyìì ì륌 ì¶ê°íê±°ë ì ê±°í©ëë€. - ë íì©/ë¹íì©(Nullability/Non-nullability):
| nullëë| undefined륌 ì¶ê°íê±°ë ì ê±°í©ëë€.
ìì 2: íì ì ìœêž° ì ì© ë²ì ìì±íêž°
ìì±ì ì íì ìŒë¡ ë§ëë ê²ê³Œ ì ì¬íê², ReadonlyUser íì
ì ë§ë€ ì ììµëë€:
type ReadonlyUser = {
readonly [P in keyof User]: User[P];
};
ìŽê²ì ë€ìì ìì±í ê²ì ëë€:
{
readonly id: number;
readonly name: string;
readonly email: string;
readonly isActive: boolean;
}
ìŽë í¹ì ë°ìŽí° êµ¬ì¡°ê° ìŒëš ìì±ë멎 ë³ê²œë ì ìëë¡ ë³Žì¥íë ë° ë§€ì° ì ì©íë©°, í¹í ëìì± í겜ìŽë ë§ì êµì ê°ë° íìŽ ì±íí íšìí íë¡ê·žëë° íšë¬ë€ììì ìžêž° ìë ë¶ë³ ë°ìŽí° íšíŽì ë€ë£° ë ê°ë ¥íê³ ììž¡ ê°ë¥í ìì€í ì 구ì¶íêž° ìí 귌볞ì ìž ìì¹ì ëë€.
ìì 3: ì íì± ë° ìœêž° ì ì© ê²°í©íêž°
ìì ì륌 ê²°í©í ì ììµëë€. ì륌 ë€ìŽ, ìì±ìŽ ì íì ìŽë©Žì ëìì ìœêž° ì ì©ìž íì :
type OptionalReadonlyUser = {
readonly [P in keyof User]?: User[P];
};
ê·ž 결곌ë ë€ì곌 ê°ìµëë€:
{
readonly id?: number;
readonly name?: string;
readonly email?: string;
readonly isActive?: boolean;
}
ë§€íë íì ìŒë¡ ìì ì ì ê±°íêž°
ìì ì륌 ì ê±°íê³ ì¶ë€ë©Ž ìŽë»ê² íŽìŒ í ê¹ì? TypeScriptë ë§€íë íì
ëŽìì -? ë° -readonly 구묞ì ì¬ì©íì¬ ìŽë¥Œ íì©í©ëë€. ìŽë Ʞ졎 ì ížëŠ¬í° íì
ëë ë³µì¡í íì
êµ¬ì± ìì륌 ë€ë£° ë í¹í ê°ë ¥í©ëë€.
Partial<T> íì
(ëŽì¥ëìŽ ììŒë©° 몚ë ìì±ì ì íì ìŒë¡ ë§ëŠ)ìŽ ìë€ê³ ê°ì íŽ ëŽ
ìë€. ê·žëŠ¬ê³ Partial<T>ì ëìŒíì§ë§ 몚ë ìì±ìŽ ë€ì íìì ìŒë¡ ë§ë€ìŽì§ íì
ì ë§ë€ê³ ì¶ë€ê³ íŽëŽ
ìë€.
type Mandatory<T> = {
-?: T extends object ? T[keyof T] : never;
};
type FullyPopulatedUser = Mandatory<Partial<User>>;
ìŽê²ì ì§êŽì ìŽì§ ìê² ë³Žì ëë€. ë¶ìíŽ ëŽ ìë€:
Partial<User>ë ì°ëЬì OptionalUserì ëìŒí©ëë€. ìŽì ê·ž ìì±ë€ì íìë¡ ë§ë€ê³ ì¶ìµëë€. -? 구묞ì ì íì ìì ì륌 ì ê±°í©ëë€.
Partialì 뚌ì ì졎íì§ ìê³ ìŽë¥Œ ë¬ì±íë ë ì§ì ì ìž ë°©ë²ì ëšìí ì볞 íì
ì ê°ì žìì ì íì ìŽìë€ë©Ž íìë¡ ë§ëë ê²ì
ëë€:
type MakeMandatory<T> = {
-?: T;
};
type MandatoryUser = MakeMandatory<OptionalUser>;
ìŽë ê² í멎 OptionalUserê° ìëì User íì
구조(몚ë ìì±ìŽ ì¡Žì¬íê³ íìì ì)ë¡ ì¬ë°ë¥Žê² ëëìê°ëë€.
ë§ì°¬ê°ì§ë¡, readonly ìì ì륌 ì ê±°íë €ë©Ž:
type Mutable<T> = {
-readonly [P in keyof T]: T[P];
};
type MutableUser = Mutable<ReadonlyUser>;
MutableUserë ìë User íì
곌 ëìŒíì§ë§, ìì±ìŽ ìœêž° ì ì©ìŽ ìë ê²ì
ëë€.
ë íì© ë° ë¯žì ì íì© ì¬ë¶
ë íì© ì¬ë¶ë ì ìŽí ì ììµëë€. ì륌 ë€ìŽ, 몚ë ìì±ìŽ íì€í nullìŽ ìëì 볎ì¥íë €ë©Ž:
type NonNullableValues<T> = {
[P in keyof T]-?: NonNullable<T[P]>;
};
interface MaybeNull {
name: string | null;
age: number | undefined;
}
type DefiniteValues = NonNullableValues<MaybeNull>;
// type DefiniteValues = {
// name: string;
// age: number;
// }
ì¬êž°ì -?ë ìì±ìŽ ì í ì¬íìŽ ìëì 볎ì¥íê³ , NonNullable<T[P]>ë ê° íì
ìì null곌 undefined륌 ì ê±°í©ëë€.
ìì± í€ ë³ííêž°
ë§€íë íì ì 믿ì ì ìì ì ëë¡ ë€ì¬ë€ë¥íë©°, ê°ìŽë ìì ì륌 ë³ê²œíë ë° ê·žì¹ì§ ììµëë€. ê°ì²Ž íì ì í€ë ë³íí ì ììµëë€. ìŽê²ìŽ ë§€íë íì ìŽ ë³µì¡í ìë늬ì€ìì ì§ì ìŒë¡ ë¹ì ë°íë ì§ì ì ëë€.
ìì 4: ìì± í€ì ì ëì¬ ì¶ê°íêž°
Ʞ졎 íì ì 몚ë ìì±ì í¹ì ì ëì¬ê° ë¶ë ìë¡ìŽ íì ì ë§ë€ê³ ì¶ë€ê³ ê°ì íŽ ëŽ ìë€. ìŽë ë€ìì€íìŽì± ëë ë°ìŽí° 구조ì ë³íì ìì±íë ë° ì ì©í ì ììµëë€.
type Prefixed<T, Prefix extends string> = {
[P in keyof T as `${Prefix}${Capitalize<string & P>}`]: T[P];
};
type OriginalConfig = {
timeout: number;
retries: number;
};
type PrefixedConfig = Prefixed<OriginalConfig, 'app'>;
// type PrefixedConfig = {
// appTimeout: number;
// appRetries: number;
// }
í€ ë³íì ë¶ìíŽ ëŽ ìë€:
P in keyof T: ì¬ì í ì볞 í€ë€ì ë°ë³µí©ëë€.as `${Prefix}${Capitalize<string & P>}`: ìŽê²ì í€ ì¬ë§€í(remapping) ì ì ëë€.`${Prefix}${...}`: ìŽë í í늿 늬í°ëŽ íì (template literal types)ì ì¬ì©íì¬ ì ê³µëPrefixì ë³íë ìì± ìŽëŠì ì°ê²°íì¬ ì í€ ìŽëŠì 구ì±í©ëë€.Capitalize<string & P>: ìŽë ìì± ìŽëŠPê° ë¬žììŽë¡ ì²ëЬë ë€ì ë묞ìë¡ ë³íëëë¡ íë ìŒë°ì ìž íšíŽì ëë€.string & P륌 ì¬ì©íì¬Pìstringì êµì°šììŒ TypeScriptê° ìŽë¥Œ 묞ììŽ íì ìŒë¡ ì²ëЬíëë¡ ë³Žì¥íë©°, ìŽëCapitalizeì íìí©ëë€.
ìŽ ììë Ʞ졎 ìì±ì êž°ë°ìŒë¡ ìì± ìŽëŠì ëì ìŒë¡ ë³ê²œíë ë°©ë²ì 볎ì¬ì£Œëë°, ìŽë ì í늬ìŒìŽì ì ì¬ë¬ ê³ìžµìì ìŒêŽì±ì ì ì§íê±°ë í¹ì ëª ëª ê·ì¹ì ê°ì§ ìžë¶ ìì€í 곌 íµí©í ë ê°ë ¥í êž°ì ì ëë€.
ìì 5: ìì± íí°ë§íêž°
í¹ì 조걎ì ë§ì¡±íë ìì±ë§ í¬íšíê³ ì¶ë€ë©Ž ìŽëšê¹ì? ìŽë ë§€íë íì
곌 ì¡°ê±Žë¶ íì
(Conditional Types)ì í€ ì¬ë§€íì ìí as ì 곌 ê²°í©íì¬ ë¬ì±í ì ììŒë©°, ì¢
ì¢
ìì±ì íí°ë§íë ë° ì¬ì©ë©ëë€.
type OnlyStrings<T> = {
[P in keyof T as T[P] extends string ? P : never]: T[P];
};
interface MixedData {
name: string;
age: number;
city: string;
isActive: boolean;
}
type StringOnlyData = OnlyStrings<MixedData>;
// type StringOnlyData = {
// name: string;
// city: string;
// }
ìŽ ê²œì°:
T[P] extends string ? P : never: ê° ìì±Pì ëíŽ, íŽë¹ ê° íì (T[P])ìŽstringì í ë¹ ê°ë¥íì§ íìží©ëë€.- ë§ìœ 묞ììŽìŽëŒë©Ž, í€
Pë ì ì§ë©ëë€. - 묞ììŽìŽ ìëëŒë©Ž,
neverë¡ ë§€íë©ëë€. í€ê°neverë¡ ë§€íë멎, 결곌 ê°ì²Ž íì ìì ì¬ì€ì ì ê±°ë©ëë€.
ìŽ êž°ì ì ë ëì íì ìì ë 구첎ì ìž íì ì ìì±íë ë° ë§€ì° ì ì©í©ëë€. ì륌 ë€ìŽ, í¹ì íì ì êµ¬ì± ì€ì ë§ ì¶ì¶íê±°ë ë°ìŽí° íë륌 ê·ž ìì±ì ë°ëŒ ë¶ëЬíë ë° ì¬ì©ë ì ììµëë€.
ìì 6: í€ë¥Œ ë€ë¥ž ííë¡ ë³ííêž°
ëí í€ë¥Œ ìì í ë€ë¥ž ì¢ ë¥ì í€ë¡ ë³íí ì ììµëë€. ì륌 ë€ìŽ ë¬žììŽ í€ë¥Œ ì«ìë¡ ë°êŸžê±°ë ê·ž ë°ëë¡ ë°ê¿ ì ìì§ë§, ìŽë ì§ì ì ìž ê°ì²Ž ì¡°ì볎ë€ë ê³ êž íì ë 벚 íë¡ê·žëë°ìì ë ì죌 ì¬ì©ë©ëë€.
묞ììŽ í€ë¥Œ 묞ììŽ ëŠ¬í°ëŽì ì ëìšìŒë¡ ë³íí ë€ì, ìŽë¥Œ ì íì ì Ʞ볞ìŒë¡ ì¬ì©íë ê²ì ê³ ë €íŽ ë³Žìžì. ìŽ í¹ì ë°©ììŒë¡ë ë§€íë íì ì첎 ëŽìì ê°ì²Žì í€ë¥Œ ì§ì ë³ííë ê²ì ìëì§ë§, í€ê° ìŽë»ê² ì¡°ìë ì ìëì§ë¥Œ 볎ì¬ì€ëë€.
ë ì§ì ì ìž í€ ë³í ììë í€ë¥Œ ë묞ì ë²ì ìŒë¡ ë§€ííë ê²ìŒ ì ììµëë€:
type UppercaseKeys<T> = {
[P in keyof T as Uppercase<string & P>]: T[P];
};
type LowercaseData = {
firstName: string;
lastName: string;
};
type UppercaseData = UppercaseKeys<LowercaseData>;
// type UppercaseData = {
// FIRSTNAME: string;
// LASTNAME: string;
// }
ìŽë as ì ì ì¬ì©íì¬ ê° í€ P륌 íŽë¹ ë묞ì ë±ê°ë¬Œë¡ ë³íí©ëë€.
ì€ì ì ì© ì¬ë¡ ë° íì€ ìë늬ì€
ë§€íë íì ì ëšì§ ìŽë¡ ì ìž êµ¬ì± ììê° ìëëë€. ë€ìí ê°ë° ë¶ìŒì ê±žì³ ì€ìí ì€ì ì ìž ì믞륌 ê°ì§ëë€. ë€ìì ë§€íë íì ìŽ ë§€ì° ì ì©í ëª ê°ì§ ìŒë°ì ìž ìë늬ì€ì ëë€:
1. ì¬ì¬ì© ê°ë¥í ì ížëŠ¬í° íì 구ì¶
ë§ì ìŒë°ì ìž íì
ë³íì ì¬ì¬ì© ê°ë¥í ì ížëŠ¬í° íì
ìŒë¡ 캡ìíë ì ììµëë€. TypeScriptì íì€ ëŒìŽëžë¬ëЬë ìŽë¯ž Partial<T>, Readonly<T>, Record<K, T>, Pick<T, K>ì ê°ì íë¥í ììë€ì ì ê³µí©ëë€. ë§€íë íì
ì ì¬ì©íì¬ ìì ë§ì 컀ì€í
ì ížëŠ¬í° íì
ì ì ìíšìŒë¡ìš ê°ë° ìí¬íë¡ì°ë¥Œ ê°ìíí ì ììµëë€.
ì륌 ë€ìŽ, 몚ë ìì±ì ì볞 ê°ì ë°ì ì ê°ì ë°ííë íšìë¡ ë§€ííë íì :
type Mappers<T> = {
[P in keyof T]: (value: T[P]) => T[P];
};
interface ProductInfo {
name: string;
price: number;
}
type ProductMappers = Mappers<ProductInfo>;
// type ProductMappers = {
// name: (value: string) => string;
// price: (value: number) => number;
// }
2. ëì íŒ ì²ëЬ ë° ì íšì± ê²ì¬
íë¡ ížìë ê°ë°, í¹í React ëë Angularì ê°ì íë ììí¬(ì¬êž° ììë ìì TypeScriptìŽì§ë§)ìì íŒê³Œ ê·ž ì íšì± ê²ì¬ ìí륌 ë€ë£šë ê²ì ìŒë°ì ìž ìì ì ëë€. ë§€íë íì ì ê° íŒ íëì ì íšì± ê²ì¬ ìí륌 êŽëЬíë ë° ëììŽ ë ì ììµëë€.
'pristine', 'touched', 'valid', 'invalid' ìí륌 ê°ì§ ì ìë íë륌 ê°ì§ íŒì ìê°íŽ ëŽ ìë€.
type FormFieldState = 'pristine' | 'touched' | 'dirty' | 'valid' | 'invalid';
type FormState<T> = {
[P in keyof T]: FormFieldState;
};
interface UserForm {
username: string;
email: string;
password: string;
}
type UserFormState = FormState<UserForm>;
// type UserFormState = {
// username: FormFieldState;
// email: FormFieldState;
// password: FormFieldState;
// }
ìŽë¥Œ íµíŽ íŒì ë°ìŽí° 구조륌 ë°ìíì§ë§ ê° íëì ìí륌 ì¶ì íì¬ íŒ êŽëЬ ë¡ì§ì ìŒêŽì±ê³Œ íì ìì ì±ì 볎ì¥íë íì ì ë§ë€ ì ììµëë€. ìŽë ë€ìí UI/UX ì구 ì¬íìŽ ë³µì¡í íŒ ìíë¡ ìŽìŽì§ ì ìë êµì íë¡ì ížì í¹í ì ì©í©ëë€.
3. API ìëµ ë³í
API륌 ë€ë£° ë, ìëµ ë°ìŽí°ê° íì ëŽë¶ ëë©ìž 몚ëžê³Œ ì벜íê² ìŒì¹íì§ ìì ì ììµëë€. ë§€íë íì ì API ìëµì ìíë ííë¡ ë³ííë ë° ëìì ì€ ì ììµëë€.
í€ì snake_case륌 ì¬ì©íì§ë§ ì í늬ìŒìŽì ìŽ camelCase륌 ì ížíë API ìëµì ììíŽ ë³Žìžì:
// Assume this is the incoming API response type
type ApiUserData = {
user_id: number;
first_name: string;
last_name: string;
};
// Helper to convert snake_case to camelCase for keys
type ToCamelCase<S extends string>: string = S extends `${infer T}_${infer U}`
? `${T}${Capitalize<U>}`
: S;
type CamelCasedKeys<T> = {
[P in keyof T as ToCamelCase<string & P>]: T[P];
};
type AppUserData = CamelCasedKeys<ApiUserData>;
// type AppUserData = {
// userId: number;
// firstName: string;
// lastName: string;
// }
ìŽê²ì 묞ììŽ ì¡°ìì ìí ì¬ê·ì ì¡°ê±Žë¶ íì ì ì¬ì©íë ë ê³ êž ììì ëë€. íµì¬ì ë§€íë íì ìŽ ë€ë¥ž ê³ êž TypeScript êž°ë¥ê³Œ ê²°í©ë ë ë³µì¡í ë°ìŽí° ë³íì ìëííì¬ ê°ë° ìê°ì ì ìœíê³ ë°íì ì€ë¥ ìíì ì€ìŒ ì ìë€ë ê²ì ëë€. ìŽë ë€ìí ë°±ìë ìë¹ì€ì ìì íë êžë¡ë² íìê² ì€ìí©ëë€.
4. ìŽê±°í(Enum)곌 ì ì¬í 구조 ê°ì íêž°
TypeScriptì `enum`ìŽ ìì§ë§, ëë¡ë ë ë§ì ì ì°ì±ì ìíê±°ë ìŽê±°íì²ëŒ ìëíë ê°ì²Ž 늬í°ëŽìì íì ì íìíê³ ì¶ì ì ììµëë€.
const AppPermissions = {
READ: 'read',
WRITE: 'write',
DELETE: 'delete',
ADMIN: 'admin',
} as const;
type Permission = typeof AppPermissions[keyof typeof AppPermissions];
// type Permission = 'read' | 'write' | 'delete' | 'admin'
type UserPermissions = {
[P in Permission]?: boolean;
};
type RolePermissions = {
[P in Permission]: boolean;
};
const userPerms: UserPermissions = {
read: true,
};
const adminRole: RolePermissions = {
read: true,
write: true,
delete: true,
admin: true,
};
ì¬êž°ì ì°ëЬë 뚌ì ê°ë¥í 몚ë ê¶í 묞ììŽì ì ëìš íì ì íììíµëë€. ê·žë° ë€ì ë§€íë íì ì ì¬ì©íì¬ ê° ê¶íìŽ í€ìž íì ì ìì±íšìŒë¡ìš, ì¬ì©ìê° íŽë¹ ê¶íì ê°ì§ê³ ìëì§(ì í ì¬í) ëë ìí ìŽ ìŽë¥Œ íìë¡ íëì§(íì ì¬í) ì§ì í ì ììµëë€. ìŽ íšíŽì ì ìžê³ì ê¶í ë¶ì¬ ìì€í ìì íí ì¬ì©ë©ëë€.
ëì 곌ì ë° ê³ ë € ì¬í
ë§€íë íì ì ë§€ì° ê°ë ¥íì§ë§, ì ì¬ì ìž ë³µì¡ì±ì ì ìíë ê²ìŽ ì€ìí©ëë€:
- ê°ë ì± ë° ë³µì¡ì±: ì§ëì¹ê² ë³µì¡í ë§€íë íì ì í¹í ìŽë¬í ê³ êž êž°ë¥ì ìµìíì§ ìì ê°ë°ììê² ìœê³ ìŽíŽíêž° ìŽë €ìž ì ììµëë€. íì ëª íì±ì ìíŽ ë žë ¥íê³ , 죌ìì ì¶ê°íê±°ë ë³µì¡í ë³íì ìžë¶ííë ê²ì ê³ ë €íìžì.
- ì±ë¥ ìí¥: TypeScriptì íì ê²ì¬ë 컎íìŒ íìì ìŽë£šìŽì§ì§ë§, ê·¹ëë¡ ë³µì¡í íì ì¡°ìì ìŽë¡ ì ìŒë¡ 컎íìŒ ìê°ì ìœê° ìŠê°ìí¬ ì ììµëë€. ëë¶ë¶ì ì í늬ìŒìŽì ììë ìŽë 믞믞íì§ë§, ë§€ì° í° ìœëë² ìŽì€ë ì±ë¥ìŽ ì€ìí ë¹ë íë¡ìžì€ììë ìŒëì ëìŽìŒ í ì ì ëë€.
- ëë²ê¹ : ë§€íë íì ìŽ ììì¹ ëª»í 결곌륌 ìì±í ë ëë²ê¹ ìŽ ìŽë €ìž ì ììµëë€. TypeScript Playground ëë IDEì íì ê²ì¬ êž°ë¥ì ì¬ì©íë ê²ìŽ íì ìŽ ìŽë»ê² íŽìëëì§ ìŽíŽíë ë° ì€ìí©ëë€.
- `keyof` ë° ë£©ì íì ìŽíŽ: ë§€íë íì ì íšê³Œì ìŒë¡ ì¬ì©íë €ë©Ž `keyof` ë° ë£©ì íì (`T[P]`)ì ëí ê²¬ê³ í ìŽíŽê° íìí©ëë€. íìŽ ìŽë¬í Ʞ볞 ê°ë ì ì ìŽíŽíê³ ìëì§ íìžíìžì.
ë§€íë íì ì¬ì©ì ìí ëªšë² ì¬ë¡
ë§€íë íì ì 몚ë ì ì¬ë ¥ì íì©í멎ìë ê·ž ëì 곌ì 륌 ìííë €ë©Ž ë€ì ëªšë² ì¬ë¡ë€ì ê³ ë €íìžì:
- ê°ëšíê² ììíêž°: ë³µì¡í í€ ì¬ë§€íìŽë ì¡°ê±Žë¶ ë¡ì§ì ë°ìŽë€êž° ì ì Ʞ볞ì ìž ì íì± ë° ìœêž° ì ì© ë³íë¶í° ììíìžì.
- ëŽì¥ ì ížëŠ¬í° íì
íì©íêž°:
Partial,Readonly,Record,Pick,Omit,Excludeì ê°ì TypeScriptì ëŽì¥ ì ížëŠ¬í° íì ì ìµìíŽì§ìžì. ìŽë€ì ìŒë°ì ìž ìì ì ì¶©ë¶íë©° ì í ì€ížëê³ ìŽíŽíêž° ìœìµëë€. - ì¬ì¬ì© ê°ë¥í ì ë€ëŠ íì ìì±íêž°: ìŒë°ì ìž ë§€íë íì íšíŽì ì ë€ëŠ ì ížëŠ¬í° íì ìŒë¡ 캡ìííìžì. ìŽë íë¡ì íž ì ë°ê³Œ êžë¡ë² íì ê±žì³ ìŒêŽì±ì ìŽì§íê³ ìì©êµ¬ ìœë륌 ì€ì ëë€.
- ìì ì ìž ìŽëŠ ì¬ì©íêž°: ë§€íë íì
곌 ì ë€ëŠ ë§€ê°ë³ìì 목ì ì ëª
íí ëíëŽëë¡ ìŽëŠì ì§ì íìžì(ì:
Optional<T>,DeepReadonly<T>,PrefixedKeys<T, Prefix>). - ê°ë ì± ì°ì : ë§€íë íì ìŽ ë묎 ë³µì¡íŽì§ë€ë©Ž, ëìŒí 결곌륌 ë¬ì±íë ë ê°ëší ë°©ë²ìŽ ìëì§ ëë ì¶ê°ë ë³µì¡ì±ì ê°ìí ê°ì¹ê° ìëì§ ê³ ë €íìžì. ëë¡ë ìœê° ë ì¥í©íì§ë§ ë ëª íí íì ì ìê° ì ížë ì ììµëë€.
- ë³µì¡í íì 묞ìí: ë³µì¡í ë§€íë íì ì 겜ì°, í¹í ë€ìí êµì í곌 ìœë륌 ê³µì í ë JSDoc 죌ìì ì¶ê°íì¬ êž°ë¥ì ì€ëª íìžì.
- íì í ì€ížíêž°: ë§€íë íì ìŽ ììëë¡ ìëíëì§ íìžíêž° ìíŽ íì í ì€ížë¥Œ ìì±íê±°ë ìì륌 ì¬ì©íìžì. ìŽë 믞ë¬í ë²ê·žë¥Œ ì¡êž° ìŽë €ìž ì ìë ë³µì¡í ë³íì í¹í ì€ìí©ëë€.
ê²°ë¡
TypeScript ë§€íë íì ì ê³ êž íì ì¡°ìì ìŽììŒë¡, ê°ë°ììê² ê°ì²Ž íì ì ë³ííê³ ì¡°ì í ì ìë íìí êž°ë¥ì ì ê³µí©ëë€. ìì±ì ì íì ìŒë¡ ë§ë€ê±°ë, ìœêž° ì ì©ìŒë¡ ë§ë€ê±°ë, ìŽëŠì ë°êŸžê±°ë, ë³µì¡í 조걎ì ë°ëŒ íí°ë§íë ë±, ë§€íë íì ì ë°ìŽí° 구조륌 êŽëЬíë ì ìžì ìŽê³ íì ìì íë©° ë§€ì° ííë ¥ìŽ íë¶í ë°©ë²ì ì ê³µí©ëë€.
ìŽë¬í êž°ì ì ë§ì€í°íšìŒë¡ìš ìœë ì¬ì¬ì©ì±ì í¬ê² í¥ììí€ê³ , íì ìì ì±ì ê°ì íë©°, ëì± ê°ë ¥íê³ ì ì§ ë³Žì ê°ë¥í ì í늬ìŒìŽì ì 구ì¶í ì ììµëë€. ë§€íë íì ì íì ë°ìë€ì¬ TypeScript ê°ë°ì í ëšê³ ë ë°ì ìí€ê³ , êžë¡ë² ì²ì€ì ìí ê³ íì§ ìíížìšìŽ ì룚ì 구ì¶ì êž°ì¬íììì€. ë€ìí ì§ìì ê°ë°ìë€ê³Œ íë ¥í ë, ìŽë¬í ê³ êž íì íšíŽì íì ìì€í ì ì격íšì íµíŽ ì ì¬ì ìž ìì¬ìíµ ê²©ì°šë¥Œ ì€ìŽê³ ìœë íì§ê³Œ ìŒêŽì±ì 볎ì¥íë ê³µíµ ìžìŽ ìí ì í ì ììµëë€.