0Pricing
TypeScript Academy · 강의

제네릭 인터페이스와 타입 별칭

제네릭 인터페이스와 타입 별칭을 정의하고, 제약 조건과 기본값을 추가하며 각각 어떤 상황에서 유용한지 이해합니다.

제네릭 인터페이스와 타입 별칭은(는) CoddyKit의 무료 TypeScript Academy 강의입니다. 이것은 3개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 TypeScript Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. TypeScript Academy 강의에는 총 3개의 강의가 포함되어 있습니다.

소개

목표: 제네릭 인터페이스와 타입 별칭을 사용해 재사용 가능한 형태를 만듭니다. 제약 조건과 기본값을 추가하고 주요 차이점도 알아봅니다.

수업 개요

목표: 구조화된 동시성을 coroutineScope와 함께 적용하고, 예외 전파를 이해하며, 취소 도구를 안전하게 사용합니다.

핵심 아이디어

  • coroutineScope는 모든 하위 작업을 기다리며, 하나가 실패하면 형제 작업을 취소합니다.
  • launch는 범위 안에서 즉시 실패하고, async는 await()에서 오류를 드러냅니다.
  • withTimeout은 제한 시간이 지나면 작업을 취소합니다.
  • try/catch로 범위를 감싸 예외를 처리합니다.

제네릭 인터페이스

제네릭 인터페이스는 타입 매개변수를 가집니다. 호출자는 구체적인 타입으로 대체합니다(예: Box<number>).

interface Box<T> {
  value: T;
}

const nBox: Box<number> = { value: 42 };
const sBox: Box<string> = { value: "ts" };
console.log(nBox.value, sBox.value);

제네릭 타입 별칭

타입 별칭도 제네릭으로 만들 수 있으며 객체, 함수, 유니언 또는 인터섹션을 표현할 수 있습니다.

type Pair<A, B> = { first: A; second: B };

const p1: Pair<number, string> = { first: 1, second: "one" };
const p2: Pair<boolean, boolean> = { first: true, second: false };
console.log(p1, p2);

범위의 대기 동작

coroutineScope는 하위 작업이 모두 끝난 후에만 완료되는 하위 범위를 만듭니다.

import kotlinx.coroutines.*

suspend fun doTwoTasks(): Unit = coroutineScope {
    // Both run concurrently and the scope waits for them
    launch { delay(150); println("Task A done") }
    launch { delay(100); println("Task B done") }
    // returning Unit implicitly after children complete
}

fun main() = runBlocking {
    doTwoTasks()
    println("Scope completed")
}

실패 시 형제 작업 취소

하위 작업 하나가 예외를 발생시키면 범위가 형제 작업을 취소하고 호출자에게 예외를 다시 전달합니다. 호출 위치에서 try/catch를 사용합니다.

import kotlinx.coroutines.*

suspend fun failingGroup() = coroutineScope {
    val a = launch {
        try {
            repeat(5) { i ->
                println("A $i"); delay(60)
            }
        } finally {
            println("A cancelled")
        }
    }
    launch {
        delay(120)
        throw IllegalStateException("boom") // failure in child
    }
    a.join() // will be cancelled when sibling fails
}

fun main() = runBlocking {
    try {
        failingGroup()
    } catch (e: Exception) {
        println("Caught in caller: ${e.message}")
    }
    println("Caller continues")
}

제약 조건

extends 제약 조건을 추가하면 T가 필요한 멤버(예: id)를 인터페이스 메서드에 제공하도록 할 수 있습니다.

interface Repository<T extends { id: number }> {
  getById(id: number): T | undefined;
  save(entity: T): void;
}

type User = { id: number; name: string };

const memRepo: Repository<User> = {
  store: [] as User[],
  getById(id) {
    return this.store.find(u => u.id === id);
  },
  save(u) {
    this.store.push(u);
  }
} as unknown as Repository<User>;

memRepo.save({ id: 1, name: "Ada" });
console.log(memRepo.getById(1));

async와 await 오류

async의 예외는 await()를 호출할 때 발생합니다. try/catch로 처리합니다.

import kotlinx.coroutines.*

suspend fun parseAsync(s: String) = coroutineScope {
    val deferred = async {
        delay(50)
        s.toInt() // may throw NumberFormatException
    }
    try {
        println("Result = ${deferred.await()}") // error appears here
    } catch (e: NumberFormatException) {
        println("Handled parse error: ${e::class.simpleName}")
    }
}

fun main() = runBlocking {
    parseAsync("12")
    parseAsync("xx")
}

기본값과 확장

편리한 사용을 위해 기본 타입 매개변수를 제공하고, 유틸리티로 타입을 확장합니다(예: Readonly<Box<T>>).

interface ApiResponse<T = unknown> {
  data: T;
  ok: boolean;
}

type ReadonlyBox<T> = Readonly<Box<T>>;

const r1: ApiResponse = { data: "ok", ok: true };      // T defaults to unknown
const r2: ApiResponse<number> = { data: 200, ok: true };
const rb: ReadonlyBox<string> = { value: "fixed" };
// rb.value = "change"; // Error: readonly

withTimeout 취소

withTimeout을 사용하여 작업 시간을 제한합니다. 이 함수는 하위 작업을 취소하고 TimeoutCancellationException을 발생시킵니다.

import kotlinx.coroutines.*

suspend fun slowOp(): Int {
    delay(300) // pretend work
    return 42
}

fun main() = runBlocking {
    try {
        val result = withTimeout(150) { slowOp() } // cancels after 150ms
        println("Got $result")
    } catch (e: TimeoutCancellationException) {
        println("Timed out and cancelled")
    }
}

병합의 차이

인터페이스는 선언 병합을 지원합니다. 타입 별칭은 병합할 수 없으며, 중복된 이름은 오류입니다.

interface Settings { theme: string }
interface Settings { lang: string }
// Merged: Settings has { theme: string; lang: string }
const s: Settings = { theme: "dark", lang: "en" };

// type Settings = { foo: string };
// Error: Duplicate identifier 'Settings' for type aliases (no merging)

구조화된 동시성의 실패 규칙

coroutineScope에서 하위 코루틴 하나가 예외로 실패하면 어떻게 되나요?

인터페이스와 타입 확인

빠른 확인: 제네릭 인터페이스와 타입 별칭에 대한 설명 중 TRUE인 것은 무엇입니까?

요약

요약: 재사용 가능한 형태를 모델링할 때 제네릭 인터페이스와 타입 별칭을 사용합니다. 제약 조건과 기본값을 추가하고, 인터페이스만 병합된다는 점을 기억합니다.

요약

요약: 작업을 그룹화하려면 coroutineScope를 사용하고, 실패한 하위 작업은 형제 작업을 취소합니다. try/catch로 오류를 처리하고, await()에서 async 실패를 드러내며, withTimeout으로 오래 걸리는 작업을 취소합니다.

자주 묻는 질문

“제네릭 인터페이스와 타입 별칭” 강의는 무료인가요?

네 — “제네릭 인터페이스와 타입 별칭” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 TypeScript Academy 강의 전체를 잠금 해제할 수 있습니다. TypeScript Academy 강의에는 총 3개의 강의가 포함되어 있습니다.

“제네릭 인터페이스와 타입 별칭”에서 뭘 배우나요?

제네릭 인터페이스와 타입 별칭을 정의하고, 제약 조건과 기본값을 추가하며 각각 어떤 상황에서 유용한지 이해합니다. 브라우저에서 직접 실행하는 실습 코드로 TypeScript Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

TypeScript Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 TypeScript Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 3개 중 1번째 강의입니다.

“제네릭 인터페이스와 타입 별칭” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 TypeScript Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 TypeScript Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 제네릭 인터페이스와 타입 별칭
  2. 조건부 타입(입문)과 유니온에 대한 분배
  3. 데이터 모델을 위한 재사용 가능한 패턴
← TypeScript Academy(으)로 돌아가기