Funções Geradoras no TypeScript
Este artigo explica as funções geradoras no TypeScript.
Você pode aprender desde o básico de como usar funções geradoras até exemplos avançados combinados com processamento assíncrono, juntamente com exemplos de código.
YouTube Video
Funções Geradoras
As funções geradoras no TypeScript fornecem funcionalidade semelhante às funções geradoras do JavaScript. As funções geradoras são definidas usando function*
(uma declaração de função com um asterisco) e são funções especiais que podem pausar e retomar a execução, diferentemente das funções normais.
Quando uma função geradora é chamada, um iterador é retornado, que gera valores um de cada vez através deste iterador, e você pode pausar a execução usando a palavra-chave yield
ou enviar valores a partir de fora.
Sintaxe Básica das Funções Geradoras
1function* myGenerator(): Generator<number, void, unknown> {
2 yield 1;
3 yield 2;
4 yield 3;
5}
6
7const gen = myGenerator();
8
9console.log(gen.next().value); // 1
10console.log(gen.next().value); // 2
11console.log(gen.next().value); // 3
12console.log(gen.next().done); // true (Iteration finished)
- Defina uma função geradora com
function* myGenerator()
. - A palavra-chave
yield
pausa a execução da função ao retornar um valor. - Cada vez que o método
next()
é chamado, a execução da função geradora é retomada e avança para o próximoyield
.
next()
retorna um objeto contendo o próximo valor e uma propriedade done
. Quando done
é true
, isso indica que todos os valores foram gerados e o processamento do gerador está completo.
Aplicações das Funções Geradoras
Usar funções geradoras permite uma representação fácil de processamento sequencial. No exemplo a seguir, criamos uma função geradora que gera uma sequência de números.
1function* sequenceGenerator(start: number = 0, step: number = 1) {
2 let current = start;
3 while (true) {
4 yield current;
5 current += step;
6 }
7}
8
9const seq = sequenceGenerator(1, 2);
10
11console.log(seq.next().value); // 1
12console.log(seq.next().value); // 3
13console.log(seq.next().value); // 5
- Neste exemplo,
sequenceGenerator
gera uma sequência indefinidamente crescente de números. Useyield
para retornar valores em cada etapa e gere o próximo valor em chamadas subsequentes.
Passando Valores para next
O método next()
pode receber um valor, que pode ser enviado para a função geradora.
1function* adder() {
2 const num1 = yield;
3 const num2 = yield;
4 yield num1 + num2;
5}
6
7const addGen = adder();
8addGen.next(); // Initialization
9addGen.next(5); // Set 5 to num1
10const result = addGen.next(10).value; // Set 10 to num2 and get result
11console.log(result); // 15
- Neste exemplo,
next(5)
enext(10)
enviam seus respectivos valores para a função geradora, eyield num1 + num2
retorna a soma deles.
return
e throw
return(value)
pode finalizar o gerador e retornar o valor especificado.throw(error)
pode lançar uma exceção dentro do gerador, usado para tratar exceções dentro do gerador.
1function* testGenerator() {
2 try {
3 yield 1;
4 yield 2;
5 } catch (e) {
6 console.error("Error caught:", e);
7 }
8}
9
10const gen = testGenerator();
11console.log(gen.next().value); // 1
12gen.throw(new Error("An error occurred!")); // Error caught: An error occurred!
- Neste exemplo, o método
throw
é usado para gerar um erro dentro do gerador, e esse erro é capturado dentro do gerador.
Definição de Tipo em TypeScript
A definição de tipo de uma função geradora pode ser especificada no seguinte formato.
1// Generator<YieldType, ReturnType, NextType>
2function* myGenerator(): Generator<number, void, unknown> {
3 yield 1;
4 yield 2;
5 yield 3;
6}
- Você especifica os tipos na forma de
Generator<YieldType, ReturnType, NextType>
.YieldType
é o tipo do valor retornado poryield
.ReturnType
é o tipo do valor retornado porreturn
.NextType
é o tipo do valor passado paranext()
.
No exemplo a seguir, tipos específicos são especificados para usar o gerador de forma segura com tipos.
1function* numberGenerator(): Generator<number, void, number> {
2 const num1 = yield 1;
3 const num2 = yield num1 + 2;
4 yield num2 + 3;
5}
6
7const gen = numberGenerator();
8
9console.log(gen.next().value); // 1
10console.log(gen.next(10).value); // 12 (10 + 2)
11console.log(gen.next(20).value); // 23 (20 + 3)
Geradores e Processamento Assíncrono
Geradores também podem ser utilizados para processamento assíncrono. Por exemplo, você pode usar yield
para aguardar os resultados de operações assíncronas enquanto continua o processamento sequencial. No entanto, em TypeScript ou JavaScript, async/await
é mais comumente usado.
1function* asyncTask() {
2 const result1 = yield fetch("https://codesparklab.com/json/example1.json");
3 console.log(result1);
4
5 const result2 = yield fetch("https://codesparklab.com/json/example2.json");
6 console.log(result2);
7}
Assim, embora seja possível processar operações assíncronas sequencialmente com geradores, eles não são frequentemente usados para processamento assíncrono porque Promises e async
/await
são mais convenientes.
Resumo
- Funções geradoras são funções especiais definidas com
function*
que podem retornar valores comyield
enquanto pausam a execução da função. - Use
next()
para retomar o gerador e receber valores. Além disso, você pode enviar valores para o gerador usandonext(value)
. - Você pode usar
return()
ethrow()
para terminar funções geradoras ou lidar com erros. - Ao usar geradores em TypeScript, você pode utilizar definições de tipo para escrever código com segurança de tipos.
Geradores são ferramentas poderosas que permitem controlar a iteração de forma flexível.
Você pode acompanhar o artigo acima usando o Visual Studio Code em nosso canal do YouTube. Por favor, confira também o canal do YouTube.