0Pricing
TypeScript Academy · Lección

Interfaces y alias de tipo genéricos

Defina interfaces y alias de tipo genéricos; añada restricciones y valores predeterminados, y comprenda en qué situaciones destaca cada uno.

Interfaces y alias de tipo genéricos es una lección gratuita de TypeScript Academy en CoddyKit. Esta es la lección 1 de 3. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de TypeScript Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de TypeScript Academy incluye 3 lecciones en total.

Introducción

Objetivo: Crear estructuras reutilizables mediante interfaces genéricas y alias de tipo. Añadirá restricciones y valores predeterminados, y aprenderá sus diferencias principales.

Descripción general de la lección

Objetivo: aplicar la concurrencia estructurada con coroutineScope, comprender la propagación de excepciones y usar las herramientas de cancelación de forma segura.

Ideas clave

  • coroutineScope espera a todos sus hijos; un fallo cancela a los hermanos.
  • launch falla inmediatamente en el ámbito; async hace visibles los errores al llamar a await().
  • withTimeout cancela el trabajo tras un límite.
  • Envuelva los ámbitos con try/catch para gestionar las excepciones.

Interfaz genérica

Una interfaz genérica contiene un parámetro de tipo. Quienes llamen sustituyen tipos concretos (por ejemplo, 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);

Alias de tipo genérico

Un alias de tipo también puede ser genérico y expresar objetos, funciones, uniones o intersecciones.

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);

Comportamiento de espera de coroutineScope

coroutineScope crea un ámbito hijo que se completa solo después de que terminan sus hijos.

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")
}

Un fallo cancela a los hermanos

Si un hijo lanza una excepción, el ámbito cancela a los hermanos y vuelve a lanzarla al llamador; use try/catch en el punto de llamada.

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")
}

Restricciones

Añada una restricción extends para que T exponga los miembros necesarios (por ejemplo, id) a los métodos de la interfaz.

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));

Errores de async + await

Las excepciones de async se producen cuando llama a await(); gestiónelas con 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")
}

Valores predeterminados y extensión

Proporcione parámetros de tipo predeterminados para facilitar el uso y amplíe los tipos con utilidades (por ejemplo, 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

Cancelación con withTimeout

Use withTimeout para limitar el trabajo; cancela al hijo y lanza 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")
    }
}

Diferencias de combinación

Las interfaces admiten la combinación de declaraciones. Los alias de tipo no se pueden combinar; los nombres duplicados producen errores.

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)

Regla de fallo de la concurrencia estructurada

En coroutineScope, ¿qué ocurre si una corrutina hija falla con una excepción?

Comprobación de interfaces frente a tipos

Comprobación rápida: ¿Qué afirmación sobre las interfaces genéricas y los alias de tipo es VERDADERA?

Resumen

Resumen: Utilice interfaces genéricas y alias de tipo para modelar estructuras reutilizables. Añada restricciones y valores predeterminados, y recuerde: solo las interfaces se pueden combinar.

Resumen

Resumen: Use coroutineScope para agrupar el trabajo; un hijo que falla cancela a los hermanos. Gestione los errores con try/catch, haga visibles los fallos de async mediante await() y cancele las tareas largas con withTimeout.

Preguntas frecuentes

¿La lección «Interfaces y alias de tipo genéricos» es gratis?

Sí — el texto completo de «Interfaces y alias de tipo genéricos» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de TypeScript Academy, actualiza a CoddyKit PRO. El curso de TypeScript Academy incluye 3 lecciones en total.

¿Qué aprenderé en «Interfaces y alias de tipo genéricos»?

Defina interfaces y alias de tipo genéricos; añada restricciones y valores predeterminados, y comprenda en qué situaciones destaca cada uno. Practicas TypeScript Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar TypeScript Academy?

No se requiere experiencia previa. TypeScript Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 3.

¿Cuánto tiempo toma la lección «Interfaces y alias de tipo genéricos»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de TypeScript Academy?

Sí. Cada lección de TypeScript Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Interfaces y alias de tipo genéricos
  2. Tipos condicionales (introducción) y distribución sobre uniones
  3. Patrones reutilizables para modelos de datos
← Volver a TypeScript Academy