interfaces.ts

Download
typescript 410 lines 9.9 KB
  1/**
  2 * TypeScript μΈν„°νŽ˜μ΄μŠ€μ™€ μ œλ„€λ¦­
  3 * - μΈν„°νŽ˜μ΄μŠ€
  4 * - ν΄λž˜μŠ€μ™€ νƒ€μž…
  5 * - μ œλ„€λ¦­
  6 * - μœ ν‹Έλ¦¬ν‹° νƒ€μž…
  7 */
  8
  9// ============================================
 10// 1. μΈν„°νŽ˜μ΄μŠ€ 기초
 11// ============================================
 12
 13interface User {
 14    id: number;
 15    name: string;
 16    email: string;
 17    age?: number;  // 선택적 속성
 18    readonly createdAt: Date;  // 읽기 μ „μš©
 19}
 20
 21const user1: User = {
 22    id: 1,
 23    name: "홍길동",
 24    email: "hong@example.com",
 25    createdAt: new Date()
 26};
 27
 28// user1.createdAt = new Date();  // μ—λŸ¬: readonly
 29
 30console.log("=== μΈν„°νŽ˜μ΄μŠ€ 기초 ===");
 31console.log(`μ‚¬μš©μž: ${user1.name} (${user1.email})`);
 32
 33// ============================================
 34// 2. μΈν„°νŽ˜μ΄μŠ€ ν™•μž₯
 35// ============================================
 36
 37interface Person {
 38    name: string;
 39    age: number;
 40}
 41
 42interface Employee extends Person {
 43    employeeId: string;
 44    department: string;
 45}
 46
 47interface Manager extends Employee {
 48    teamSize: number;
 49    reports: Employee[];
 50}
 51
 52const manager: Manager = {
 53    name: "κΉ€λΆ€μž₯",
 54    age: 45,
 55    employeeId: "E001",
 56    department: "κ°œλ°œνŒ€",
 57    teamSize: 5,
 58    reports: []
 59};
 60
 61console.log("\n=== μΈν„°νŽ˜μ΄μŠ€ ν™•μž₯ ===");
 62console.log(`λ§€λ‹ˆμ €: ${manager.name}, ${manager.department}, νŒ€μ› ${manager.teamSize}λͺ…`);
 63
 64// ============================================
 65// 3. μΈν„°νŽ˜μ΄μŠ€ 병합
 66// ============================================
 67
 68interface Config {
 69    apiUrl: string;
 70}
 71
 72interface Config {
 73    timeout: number;
 74}
 75
 76// 두 선언이 μžλ™μœΌλ‘œ 병합됨
 77const config: Config = {
 78    apiUrl: "https://api.example.com",
 79    timeout: 5000
 80};
 81
 82console.log("\n=== μΈν„°νŽ˜μ΄μŠ€ 병합 ===");
 83console.log(`Config: ${config.apiUrl}, timeout: ${config.timeout}ms`);
 84
 85// ============================================
 86// 4. ν•¨μˆ˜ μΈν„°νŽ˜μ΄μŠ€
 87// ============================================
 88
 89interface MathFunc {
 90    (x: number, y: number): number;
 91}
 92
 93interface Calculator {
 94    add: MathFunc;
 95    subtract: MathFunc;
 96    multiply: MathFunc;
 97    divide: MathFunc;
 98}
 99
100const calculator: Calculator = {
101    add: (x, y) => x + y,
102    subtract: (x, y) => x - y,
103    multiply: (x, y) => x * y,
104    divide: (x, y) => x / y
105};
106
107console.log("\n=== ν•¨μˆ˜ μΈν„°νŽ˜μ΄μŠ€ ===");
108console.log(`10 + 5 = ${calculator.add(10, 5)}`);
109console.log(`10 - 5 = ${calculator.subtract(10, 5)}`);
110
111// ============================================
112// 5. 인덱슀 μ‹œκ·Έλ‹ˆμ²˜
113// ============================================
114
115interface StringDictionary {
116    [key: string]: string;
117}
118
119interface NumberArray {
120    [index: number]: string;
121}
122
123const translations: StringDictionary = {
124    hello: "μ•ˆλ…•ν•˜μ„Έμš”",
125    goodbye: "μ•ˆλ…•νžˆ κ°€μ„Έμš”",
126    thanks: "κ°μ‚¬ν•©λ‹ˆλ‹€"
127};
128
129const colors: NumberArray = ["red", "green", "blue"];
130
131console.log("\n=== 인덱슀 μ‹œκ·Έλ‹ˆμ²˜ ===");
132console.log(`hello = ${translations["hello"]}`);
133console.log(`colors[0] = ${colors[0]}`);
134
135// ============================================
136// 6. ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€
137// ============================================
138
139interface Animal {
140    name: string;
141    makeSound(): void;
142}
143
144interface Movable {
145    move(distance: number): void;
146}
147
148class Dog implements Animal, Movable {
149    constructor(public name: string) {}
150
151    makeSound(): void {
152        console.log(`${this.name}: 멍멍!`);
153    }
154
155    move(distance: number): void {
156        console.log(`${this.name}이(κ°€) ${distance}m μ΄λ™ν–ˆμŠ΅λ‹ˆλ‹€.`);
157    }
158}
159
160console.log("\n=== ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€ ===");
161const dog = new Dog("바둑이");
162dog.makeSound();
163dog.move(10);
164
165// ============================================
166// 7. μ œλ„€λ¦­ 기초
167// ============================================
168
169// μ œλ„€λ¦­ ν•¨μˆ˜
170function identity<T>(arg: T): T {
171    return arg;
172}
173
174// μ œλ„€λ¦­ λ°°μ—΄ ν•¨μˆ˜
175function firstElement<T>(arr: T[]): T | undefined {
176    return arr[0];
177}
178
179// μ œλ„€λ¦­ 객체 ν•¨μˆ˜
180function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
181    return obj[key];
182}
183
184console.log("\n=== μ œλ„€λ¦­ 기초 ===");
185console.log(`identity("hello"): ${identity("hello")}`);
186console.log(`identity(42): ${identity(42)}`);
187console.log(`firstElement([1,2,3]): ${firstElement([1, 2, 3])}`);
188
189const person = { name: "홍길동", age: 25 };
190console.log(`getProperty: ${getProperty(person, "name")}`);
191
192// ============================================
193// 8. μ œλ„€λ¦­ μΈν„°νŽ˜μ΄μŠ€
194// ============================================
195
196interface ApiResponse<T> {
197    data: T;
198    status: number;
199    message: string;
200}
201
202interface UserData {
203    id: number;
204    name: string;
205}
206
207interface ProductData {
208    id: number;
209    title: string;
210    price: number;
211}
212
213const userResponse: ApiResponse<UserData> = {
214    data: { id: 1, name: "홍길동" },
215    status: 200,
216    message: "Success"
217};
218
219const productResponse: ApiResponse<ProductData> = {
220    data: { id: 1, title: "λ…ΈνŠΈλΆ", price: 1000000 },
221    status: 200,
222    message: "Success"
223};
224
225console.log("\n=== μ œλ„€λ¦­ μΈν„°νŽ˜μ΄μŠ€ ===");
226console.log(`User: ${userResponse.data.name}`);
227console.log(`Product: ${productResponse.data.title}`);
228
229// ============================================
230// 9. μ œλ„€λ¦­ 클래슀
231// ============================================
232
233class Stack<T> {
234    private items: T[] = [];
235
236    push(item: T): void {
237        this.items.push(item);
238    }
239
240    pop(): T | undefined {
241        return this.items.pop();
242    }
243
244    peek(): T | undefined {
245        return this.items[this.items.length - 1];
246    }
247
248    isEmpty(): boolean {
249        return this.items.length === 0;
250    }
251
252    size(): number {
253        return this.items.length;
254    }
255}
256
257console.log("\n=== μ œλ„€λ¦­ 클래슀 ===");
258const numberStack = new Stack<number>();
259numberStack.push(1);
260numberStack.push(2);
261numberStack.push(3);
262console.log(`Stack peek: ${numberStack.peek()}`);
263console.log(`Stack pop: ${numberStack.pop()}`);
264console.log(`Stack size: ${numberStack.size()}`);
265
266// ============================================
267// 10. μ œλ„€λ¦­ μ œμ•½ 쑰건
268// ============================================
269
270interface HasLength {
271    length: number;
272}
273
274function logLength<T extends HasLength>(arg: T): number {
275    console.log(`길이: ${arg.length}`);
276    return arg.length;
277}
278
279console.log("\n=== μ œλ„€λ¦­ μ œμ•½ 쑰건 ===");
280logLength("Hello");       // string은 length 있음
281logLength([1, 2, 3, 4]);  // array도 length 있음
282logLength({ length: 10 }); // 객체도 κ°€λŠ₯
283
284// ============================================
285// 11. μœ ν‹Έλ¦¬ν‹° νƒ€μž…
286// ============================================
287
288interface Todo {
289    title: string;
290    description: string;
291    completed: boolean;
292    createdAt: Date;
293}
294
295// Partial<T>: λͺ¨λ“  속성을 μ„ νƒμ μœΌλ‘œ
296type PartialTodo = Partial<Todo>;
297
298// Required<T>: λͺ¨λ“  속성을 ν•„μˆ˜λ‘œ
299type RequiredTodo = Required<Todo>;
300
301// Readonly<T>: λͺ¨λ“  속성을 읽기 μ „μš©μœΌλ‘œ
302type ReadonlyTodo = Readonly<Todo>;
303
304// Pick<T, K>: νŠΉμ • μ†μ„±λ§Œ 선택
305type TodoPreview = Pick<Todo, "title" | "completed">;
306
307// Omit<T, K>: νŠΉμ • 속성 μ œμ™Έ
308type TodoWithoutDate = Omit<Todo, "createdAt">;
309
310// Record<K, T>: ν‚€-κ°’ νƒ€μž… μ •μ˜
311type PageInfo = Record<"home" | "about" | "contact", { title: string }>;
312
313const pages: PageInfo = {
314    home: { title: "ν™ˆ" },
315    about: { title: "μ†Œκ°œ" },
316    contact: { title: "μ—°λ½μ²˜" }
317};
318
319console.log("\n=== μœ ν‹Έλ¦¬ν‹° νƒ€μž… ===");
320
321const partialTodo: PartialTodo = {
322    title: "μΌλΆ€λ§Œ"
323};
324
325const todoPreview: TodoPreview = {
326    title: "미리보기",
327    completed: false
328};
329
330console.log(`PartialTodo: ${JSON.stringify(partialTodo)}`);
331console.log(`TodoPreview: ${JSON.stringify(todoPreview)}`);
332console.log(`Pages: ${Object.keys(pages).join(", ")}`);
333
334// ============================================
335// 12. 쑰건뢀 νƒ€μž…
336// ============================================
337
338type IsString<T> = T extends string ? "yes" : "no";
339
340type A = IsString<string>;   // "yes"
341type B = IsString<number>;   // "no"
342
343// infer ν‚€μ›Œλ“œ
344type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
345
346type FuncReturn = GetReturnType<() => number>;  // number
347type AsyncReturn = GetReturnType<() => Promise<string>>;  // Promise<string>
348
349// Exclude, Extract
350type T1 = Exclude<"a" | "b" | "c", "a">;  // "b" | "c"
351type T2 = Extract<"a" | "b" | "c", "a" | "f">;  // "a"
352
353// NonNullable
354type T3 = NonNullable<string | null | undefined>;  // string
355
356console.log("\n=== 쑰건뢀 νƒ€μž… ===");
357console.log("IsString<string> = 'yes'");
358console.log("IsString<number> = 'no'");
359console.log("Exclude<'a'|'b'|'c', 'a'> = 'b' | 'c'");
360
361// ============================================
362// 13. λ§€ν•‘λœ νƒ€μž…
363// ============================================
364
365type Nullable<T> = {
366    [P in keyof T]: T[P] | null;
367};
368
369type Optional<T> = {
370    [P in keyof T]?: T[P];
371};
372
373type Getters<T> = {
374    [P in keyof T as `get${Capitalize<string & P>}`]: () => T[P];
375};
376
377interface Point {
378    x: number;
379    y: number;
380}
381
382type NullablePoint = Nullable<Point>;  // { x: number | null; y: number | null }
383type PointGetters = Getters<Point>;    // { getX: () => number; getY: () => number }
384
385console.log("\n=== λ§€ν•‘λœ νƒ€μž… ===");
386const nullablePoint: NullablePoint = { x: 10, y: null };
387console.log(`NullablePoint: x=${nullablePoint.x}, y=${nullablePoint.y}`);
388
389// ============================================
390// 14. ν…œν”Œλ¦Ώ λ¦¬ν„°λŸ΄ νƒ€μž…
391// ============================================
392
393type EventName = "click" | "scroll" | "mousemove";
394type Handler = `on${Capitalize<EventName>}`;  // "onClick" | "onScroll" | "onMousemove"
395
396type Greeting = `Hello, ${string}!`;
397
398const greeting: Greeting = "Hello, World!";
399
400console.log("\n=== ν…œν”Œλ¦Ώ λ¦¬ν„°λŸ΄ νƒ€μž… ===");
401console.log(`Greeting: ${greeting}`);
402console.log("Handler νƒ€μž…: 'onClick' | 'onScroll' | 'onMousemove'");
403
404// ============================================
405// μ‹€ν–‰ μ˜ˆμ‹œ
406// ============================================
407console.log("\n=== TypeScript μΈν„°νŽ˜μ΄μŠ€/μ œλ„€λ¦­ μ™„λ£Œ ===");
408console.log("컴파일: npx tsc interfaces.ts");
409console.log("μ‹€ν–‰: node interfaces.js");