0Pricing
TypeScript Academy · Aula

Interfaces genéricas e aliases de tipos

Defina interfaces genéricas e aliases de tipos; adicione restrições e valores padrão e entenda onde cada opção se destaca.

Interfaces genéricas e aliases de tipos é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 1 de 3. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de TypeScript Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de TypeScript Academy inclui 3 aulas no total.

Introdução

Objetivo: criar estruturas reutilizáveis usando interfaces genéricas e aliases de tipo. Você adicionará restrições e valores padrão, além de aprender as principais diferenças.

Visão geral da lição

Objetivo: Aplicar concorrência estruturada com coroutineScope, entender a propagação de exceções e usar ferramentas de cancelamento com segurança.

Ideias principais

  • coroutineScope aguarda todos os filhos; uma falha cancela os irmãos.
  • launch falha imediatamente no escopo; async apresenta os erros em await().
  • withTimeout cancela o trabalho após um limite.
  • Encapsule os escopos com try/catch para tratar exceções.

Interface genérica

Uma interface genérica contém um parâmetro de tipo. Os chamadores substituem tipos concretos, como 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

Um alias de tipo também pode ser genérico e expressar objetos, funções, uniões ou interseções.

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

Comportamento de espera do escopo

coroutineScope cria um escopo filho que só é concluído depois que seus filhos terminam.

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

Uma falha cancela os irmãos

Se um filho lançar uma exceção, o escopo cancela os irmãos e relança a exceção para o chamador; use try/catch no local da chamada.

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

Restrições

Adicione uma restrição extends para que T exponha os membros necessários, como id, aos métodos da interface.

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

Erros de async + await

As exceções de async são levantadas quando você chama await(); trate-as com 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 padrão e extensão

Forneça parâmetros de tipo padrão para facilitar o uso e crie novos tipos a partir de utilitários, como 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

Cancelamento com withTimeout

Use withTimeout para limitar o trabalho; ele cancela o filho e lança 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")
    }
}

Diferenças de mesclagem

As interfaces permitem a mesclagem de declarações. Os aliases de tipo não podem ser mesclados; nomes duplicados geram erros.

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)

Regra de falha da concorrência estruturada

No coroutineScope, o que acontece se uma corrotina filha falhar com uma exceção?

Verificação de interfaces versus tipos

Verificação rápida: qual afirmação sobre interfaces genéricas e aliases de tipo é TRUE?

Recapitulação

Recapitulação: use interfaces genéricas e aliases de tipo para modelar estruturas reutilizáveis. Adicione restrições e valores padrão e lembre-se: somente interfaces podem ser mescladas.

Recapitulação

Recapitulação: Use coroutineScope para agrupar o trabalho; um filho que falha cancela os irmãos. Trate os erros com try/catch, apresente as falhas de async em await() e cancele tarefas longas com withTimeout.

Perguntas Frequentes

A aula “Interfaces genéricas e aliases de tipos” é grátis?

Sim — o texto completo de “Interfaces genéricas e aliases de tipos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de TypeScript Academy, atualize para CoddyKit PRO. O curso de TypeScript Academy inclui 3 aulas no total.

O que vou aprender em “Interfaces genéricas e aliases de tipos”?

Defina interfaces genéricas e aliases de tipos; adicione restrições e valores padrão e entenda onde cada opção se destaca. Você pratica TypeScript Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar TypeScript Academy?

Nenhuma experiência prévia é necessária. TypeScript Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 3.

Quanto tempo leva a aula “Interfaces genéricas e aliases de tipos”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de TypeScript Academy?

Sim. Cada aula de TypeScript Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Interfaces genéricas e aliases de tipos
  2. Tipos condicionais (introdução) e distribuição sobre uniões
  3. Padrões reutilizáveis para modelos de dados
← Voltar para TypeScript Academy