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 env object
  • Adding environment variables via the --env-interface flag 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.jsonc defines Cloudflare resource bindings using the binding property for each service.
  • pnpm run cf-typegen executes wrangler types commands to generate TypeScript definitions automatically.
  • worker-configuration.d.ts exports the Env interface containing typed properties for every binding (e.g., next_cf_app: D1Database, AI: Ai).
  • cloudflare-env.d.ts stores the custom CloudflareEnv interface generated by the --env-interface flag.
  • Import Env from worker-configuration.d.ts in 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →