How to Generate TypeScript Types from wrangler.jsonc Bindings in Cloudflare Workers
Use the wrangler types CLI command to automatically generate a worker-configuration.d.ts file that exports a strongly-typed Env interface matching your D1, R2, Vectorize, and AI bindings defined in wrangler.jsonc.
The ifindev/fullstack-next-cloudflare repository demonstrates a streamlined workflow for keeping TypeScript definitions synchronized with Cloudflare Worker bindings. By generating TypeScript types from wrangler.jsonc bindings, you eliminate manual interface maintenance and gain compile-time safety when accessing D1 databases, R2 buckets, and AI services within your Next.js application.
Understanding wrangler.jsonc Bindings
Cloudflare Workers expose resources like databases and storage through bindings declared in wrangler.jsonc. In the fullstack-next-cloudflare project, these bindings include D1 databases, R2 buckets, Vectorize indexes, and the AI service.
The configuration file defines each binding with a specific name that becomes a property on the env object:
// wrangler.jsonc
{
"d1_databases": [
{ "binding": "next_cf_app", "database_name": "next-cf-app" }
],
"r2_buckets": [
{ "binding": "next_cf_app_bucket", "bucket_name": "next-cf-app-bucket" }
],
"vectorize": [
{ "binding": "VECTORIZE", "index_name": "next-cf-app-index" }
],
"ai": {
"binding": "AI"
}
}
These binding names (next_cf_app, next_cf_app_bucket, VECTORIZE, AI) must be reflected in TypeScript to enable autocomplete and type checking.
Running the Type Generation Script
The project automates type generation through an npm script named cf-typegen defined in package.json. This script executes two complementary Wrangler commands to generate TypeScript types from wrangler.jsonc bindings:
// package.json
{
"scripts": {
"cf-typegen": "pnpm exec wrangler types && pnpm exec wrangler types --env-interface CloudflareEnv ./cloudflare-env.d.ts"
}
}
The first command generates the standard runtime types, while the second creates a custom environment interface. To execute the generation:
pnpm run cf-typegen
Alternatively, run the commands individually:
wrangler types
wrangler types --env-interface CloudflareEnv ./cloudflare-env.d.ts
The Generated TypeScript Interfaces
After running the script, two declaration files provide complete type coverage for your Cloudflare bindings.
worker-configuration.d.ts
This file contains the auto-generated Env interface within the Cloudflare namespace. According to the source code, it maps each binding to its corresponding Cloudflare type:
// worker-configuration.d.ts
declare namespace Cloudflare {
interface Env {
NEXTJS_ENV: string;
CLOUDFLARE_ACCOUNT_ID: string;
next_cf_app_bucket: R2Bucket;
next_cf_app: D1Database;
VECTORIZE: VectorizeIndex;
AI: Ai;
ASSETS: Fetcher;
}
}
export type { Cloudflare };
export type Env = Cloudflare.Env;
cloudflare-env.d.ts
The second command generates ./cloudflare-env.d.ts at the project root, creating the CloudflareEnv interface that worker-configuration.d.ts re-exports. This separation allows you to extend or modify the environment interface without touching auto-generated files.
Using the Env Type in Your Code
Import the Env type from worker-configuration.d.ts to access bindings with full IntelliSense and compile-time validation.
R2 Bucket Operations
// src/lib/r2.ts
import type { Env } from '../../worker-configuration';
export async function uploadFile(env: Env, key: string, body: Uint8Array) {
// TypeScript knows env.next_cf_app_bucket is an R2Bucket
await env.next_cf_app_bucket.put(key, body);
}
D1 Database Queries
// src/db/index.ts
import type { Env } from '../../worker-configuration';
export async function getTodos(env: Env) {
// env.next_cf_app is typed as D1Database
const { results } = await env.next_cf_app.prepare('SELECT * FROM todos').all();
return results;
}
AI Model Inference
// src/services/summarizer.service.ts
import type { Env } from '../../worker-configuration';
export async function summarize(env: Env, text: string) {
const result = await env.AI.run('@cf/meta/llama-2-7b-chat-fp16', {
messages: [{ role: 'user', content: text }],
});
return result.response;
}
When to Regenerate Types
You must regenerate TypeScript types from wrangler.jsonc bindings whenever:
- Adding or removing bindings in
wrangler.jsonc(D1 databases, R2 buckets, KV namespaces, etc.) - Renaming existing bindings that change the property names on the
envobject - Adding environment variables via the
--env-interfaceflag that need type definitions
Run pnpm run cf-typegen immediately after modifying wrangler.jsonc to prevent type mismatches between your code and the deployed Worker configuration.
Summary
wrangler.jsoncdefines Cloudflare resource bindings using thebindingproperty for each service.pnpm run cf-typegenexecuteswrangler typescommands to generate TypeScript definitions automatically.worker-configuration.d.tsexports theEnvinterface containing typed properties for every binding (e.g.,next_cf_app: D1Database,AI: Ai).cloudflare-env.d.tsstores the customCloudflareEnvinterface generated by the--env-interfaceflag.- Import
Envfromworker-configuration.d.tsin server-side modules to enable autocomplete and type safety for Cloudflare APIs.
Frequently Asked Questions
What is the difference between worker-configuration.d.ts and cloudflare-env.d.ts?
worker-configuration.d.ts is generated by the base wrangler types command and contains the complete Cloudflare namespace with the Env interface. cloudflare-env.d.ts is created by the subsequent wrangler types --env-interface CloudflareEnv command and specifically defines the custom environment interface that worker-configuration.d.ts re-exports. This two-step process allows you to namespace your environment variables separately from the auto-generated runtime types.
Can I generate types for environment variables added in the Wrangler Dashboard?
Yes. When you run wrangler types --env-interface CloudflareEnv ./cloudflare-env.d.ts, the command captures both local wrangler.jsonc bindings and environment variables defined in the Cloudflare Dashboard. These secrets and variables appear as typed properties on the Env interface, ensuring your code recognizes runtime configuration without manual type declarations.
Do I need to commit the generated .d.ts files to git?
Yes. The fullstack-next-cloudflare repository includes worker-configuration.d.ts in version control. Since these files define the contract between your TypeScript code and the Cloudflare runtime, committing them ensures consistent type checking across development environments and CI pipelines. However, always regenerate and commit updated versions after modifying wrangler.jsonc.
What happens if I forget to regenerate types after adding a binding?
TypeScript will report errors when you attempt to access the new binding on the env object, as the property will not exist on the stale Env interface. Additionally, you will lose IntelliSense for the new binding's methods (e.g., R2Bucket.put() or D1Database.prepare()), increasing the risk of runtime errors when accessing improperly typed resources.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →