
O TypeScript torna mais fácil para os desenvolvedores escrever código que não falha, detectando erros de tipo antes que o programa seja executado. Queremos que os desenvolvedores aproveitem essas ferramentas, e é por isso que, há um ano, criamos um sistema para gerar automaticamente tipos TypeScript para o tempo de execução do Cloudflare Workers. Ele permitia que os desenvolvedores vissem as conclusões de código em seus IDEs para APIs do Workers e digitassem o código de verificação antes da implantação. A cada semana, uma nova versão dos tipos seria publicada, refletindo as mudanças mais recentes.
No ano passado, recebemos muitos comentários de clientes e equipes internas sobre como poderíamos melhorar nossos tipos. Com a mudança para o sistema de compilação Bazel em preparação para o código aberto do tempo de execução, vimos uma oportunidade de reconstruir nossos tipos para serem mais precisos, fáceis de usar e simples de gerar. Hoje, temos o prazer de anunciar o próximo grande lançamento do @cloudflare/workers-types
com vários novos recursos e o código aberto dos scripts de geração automática totalmente reescritos.
Como usar o TypeScript com o Workers
Configurar o TypeScript no Workers é fácil. Se está começando com o Workers, instale o Node.js e execute npx wrangler init
em seu terminal para gerar um novo projeto. Se tiver um projeto Workers existente e quiser aproveitar nossos tipos aprimorados, instale as versões mais recentes do TypeScript e @cloudflare/workers-types
com npm install --save-dev typescript @cloudflare/[email protected]
e crie um arquivo tsconfig.json
com o seguinte conteúdo:
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"lib": ["esnext"],
"types": ["@cloudflare/workers-types"]
}
}
Seu editor agora vai destacar os problemas e fornecer conclusões de código enquanto você digita, levando a uma experiência de desenvolvedor menos propensa a erros e mais agradável.

set
em vez de put
e fornecendo conclusões de códigoInteroperabilidade aprimorada com tipos padrão
O Cloudflare Workers implementa muitas das mesmas APIs de tempo de execução dos navegadores, e estamos trabalhando para melhorar ainda mais a conformidade de nossos padrões com o WinterCG. No entanto, sempre haverá diferenças fundamentais entre o que os navegadores e o Workers podem fazer. Por exemplo, os navegadores podem reproduzir arquivos de áudio, enquanto o Workers tem acesso direto à rede da Cloudflare para armazenar dados distribuídos globalmente. Essa incompatibilidade significa que as APIs de tempo de execução e os tipos fornecidos por cada plataforma são diferentes, o que dificulta o uso de tipos do Workers com estruturas, como o Remix, que executam os mesmos arquivos na rede da Cloudflare e no navegador. Esses arquivos precisam ser verificados quanto ao tipo lib.dom.d.ts
, que é incompatível com nossos tipos.
Para resolver esse problema, agora geramos uma versão separada de nossos tipos que podem ser importados seletivamente, sem a necessidade de incluir @cloudflare/workers-types
no campo de tipos do seu tsconfig.json
. Aqui está um exemplo de como fica:
import type { KVNamespace } from "@cloudflare/workers-types";
declare const USERS_NAMESPACE: KVNamespace;
Além disso, geramos automaticamente uma diferença de nossos tipos em relação a lib.webworker.d.ts
do TypeScript. No futuro, vamos usar isso para identificar áreas em que podemos melhorar ainda mais nossa conformidade com as especificações.
Compatibilidade aprimorada com datas de compatibilidade
A Cloudflare preserva as promessas sólidas de compatibilidade com versões anteriores para todas as APIs que fornecemos. Usamos sinalizadores e datas de compatibilidade para fazer alterações importantes de maneira compatível com versões anteriores. Às vezes, esses sinalizadores de compatibilidade alteram os tipos. Por exemplo, o sinalizador global_navigator
adiciona um novo navigator
global e o sinalizador url_standard
altera a assinatura do construtor URLSearchParams
.
Agora permitimos que você selecione a versão dos tipos que correspondem à sua data de compatibilidade, para que você tenha certeza de que não está usando recursos que não serão compatíveis com o tempo de execução.
{
"compilerOptions": {
...
"types": ["@cloudflare/workers-types/2022-08-04"]
}
}
Integração aprimorada com o Wrangler
Além das datas de compatibilidade, a configuração do ambiente do Workers também afeta o tempo de execução e a superfície da API de tipo. Se você tiver ligações como namespaces KV ou buckets R2 configuradas em seu wrangler.toml
, elas precisam ser refletidas nos tipos TypeScript. Da mesma forma, regras personalizadas de texto, dados e módulo WebAssembly precisam ser declaradas para que o TypeScript conheça os tipos de exportações. Anteriormente, cabia a você criar um arquivo TypeScript de ambiente separado contendo essas declarações.
Para manter o wrangler.toml
como a única fonte de verdade, agora você pode executar npx wrangler types
para gerar esse arquivo automaticamente.
Por exemplo, o seguinte wrangler.toml
…
kv_namespaces = [{ binding = "MY_NAMESPACE", id = "..." }]
rules = [{ type = "Text", globs = ["**/*.txt"] }]
…gera estes tipos de ambiente:
interface Env {
MY_NAMESPACE: KVNamespace;
}
declare module "*.txt" {
const value: string;
export default value;
}
Documentação e logs de alterações integrados aprimorados
As conclusões de código fornecem uma ótima maneira para os desenvolvedores novos na plataforma Workers explorarem a superfície da API. Agora incluímos a documentação para APIs padrão dos tipos oficiais do TypeScript em nossos tipos. Também estamos iniciando o processo de incluir documentos para APIs específicas da Cloudflare neles.

Para desenvolvedores que já usam a plataforma Workers, pode ser difícil ver como os tipos estão mudando a cada versão do @cloudflare/workers-types
. Para evitar erros de tipo e destacar novos recursos, agora geramos um log de alterações detalhado com cada versão dividindo as definições novas, alteradas e removidas.
Como a geração de tipos funciona internamente?
Conforme mencionado antes, reconstruímos completamente os scripts de geração automática de tipos para serem mais confiáveis, extensíveis e fáceis de manter. Isso significa que os desenvolvedores obterão tipos aprimorados assim que novas versões do tempo de execução forem publicadas. Nosso sistema agora usa o novo sistema do Workers, runtime-type-information (RTTI) para consultar tipos de APIs de tempo de execução do Workers, em vez de tentar extrair essas informações de C++ ASTs analisados.
// Encode the KV namespace type without any compatibility flags enabled
CompatibilityFlags::Reader flags = {};
auto builder = rtti::Builder(flags);
auto type = builder.structure<KvNamespace>();
capnp::TextCodec codec;
auto encoded = codec.encode(type);
KJ_DBG(encoded); // (name = "KvNamespace", members = [ ... ], ...)
Em seguida, passamos esse RTTI para um programa TypeScript que usa TypeScript Compiler API para gerar declarações e realizar transformações AST para organizá-las. Isso é incorporado ao sistema de compilação Bazel do workerd
, o que significa que a geração de tipos agora é um único comando bazel build //types:types
de compilação bazel. Aproveitamos o cache do Bazel para recompilar o mínimo possível durante a geração.
import ts, { factory as f } from "typescript";
const keyParameter = f.createParameterDeclaration(
/* decorators */ undefined,
/* modifiers */ undefined,
/* dotDotDotToken */ undefined,
"key",
/* questionToken */ undefined,
f.createTypeReferenceNode("string")
);
const returnType = f.createTypeReferenceNode("Promise", [
f.createUnionTypeNode([
f.createTypeReferenceNode("string"),
f.createLiteralTypeNode(f.createNull()),
]),
]);
const getMethod = f.createMethodSignature(
/* modifiers */ undefined,
"get",
/* questionToken */ undefined,
/* typeParameters */ undefined,
[keyParameter],
returnType
);
const kvNamespace = f.createInterfaceDeclaration(
/* decorators */ undefined,
/* modifiers */ undefined,
"KVNamespace",
/* typeParameters */ undefined,
/* heritageClauses */ undefined,
[getMethod]
);
const file = ts.createSourceFile("file.ts", "", ts.ScriptTarget.ESNext);
const printer = ts.createPrinter();
const output = printer.printNode(ts.EmitHint.Unspecified, kvNamespace, file);
console.log(output); // interface KVNamespace { get(key: string): Promise<string | null>; }

Embora os tipos gerados automaticamente descrevam de forma correta a interface JavaScript das APIs de tempo de execução do Workers, o TypeScript fornece recursos adicionais que podemos usar para fornecer tipos de maior fidelidade e melhorar a ergonomia do desenvolvedor. Nosso sistema nos permite escrever manualmente “substituições” parciais do TypeScript que são mescladas com os tipos gerados automaticamente. Isso nos permite…
- Adicionar parâmetros de tipo (genéricos) a tipos como
ReadableStream
e evitar valores de tiposany
. - Especificar a correspondência entre os tipos de entrada e saída com sobrecargas de método. Por exemplo,
KVNamespace#get()
deve retornar umastring
quando o argumento detype
fortext
, masArrayBuffer
quando forarrayBuffer
. - Renomear os tipos para corresponder aos padrões do TypeScript e reduzir o excesso de palavras.
- Substituir totalmente um tipo para obter declarações mais precisas. Por exemplo, substituímos
WebSocketPair
por uma declaraçãoconst
para melhores tipos comObject.values()
. - Fornecer tipos para valores que não são digitados internamente, como o objeto
Request#cf
. - Ocultar tipos internos que não podem ser usados em seu Workers.
Anteriormente, essas substituições eram definidas em arquivos TypeScript separados para as declarações C++ que estavam substituindo. Isso significava que muitas vezes elas ficavam fora de sincronia com as declarações originais. No novo sistema, as substituições são definidas juntamente com os originais com macros C++, o que significa que podem ser revisadas junto com as alterações de implementação de tempo de execução. Consulte o README do workerd
JavaScript glue code para muitos outros detalhes e exemplos.
Experimente os tipos com workers-types ainda hoje.
Recomendamos que você atualize para a versão mais recente de @cloudflare/workers-types
com npm install --save-dev @cloudflare/[email protected]
e experimente o novo comando wrangler types
. Vamos publicar uma nova versão dos tipos com cada lançamento do workerd
. Compartilhe sua opinião no Discord para desenvolvedores da Cloudflare e abra uma questão no GitHub caso encontre algum tipo que possa ser melhorado.