The env.d.ts
file is typically used for global type declarations, especially for environment variables and other globally available types. This file is automatically included in the TypeScript compilation if it’s referenced in tsconfig.json
.
Steps to Use env.d.ts
:
-
Create
env.d.ts
: Create anenv.d.ts
file at the root of your project or within atypes
directory.// env.d.ts declare namespace NodeJS { interface ProcessEnv { NEXT_PUBLIC_API_URL: string; NEXT_PUBLIC_ANALYTICS_ID: string; // Add other environment variables here } }
-
Include
env.d.ts
intsconfig.json
: Ensureenv.d.ts
is included in the TypeScript compilation by adding it to theinclude
array intsconfig.json
.// tsconfig.json { "compilerOptions": { "target": "esnext", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "baseUrl": ".", "paths": { "@/*": ["./*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "env.d.ts"], "exclude": ["node_modules"] }
Differences Between env.d.ts
and Custom Types in a Separate File:
- Purpose and Scope:
env.d.ts
: Used for global declarations, particularly environment variables and extending global namespaces.- Custom Type Files (e.g.,
types/types.ts
): Used for defining custom types, interfaces, and types specific to your application’s domain logic.
- Modularity:
env.d.ts
: Typically holds global declarations that need to be available throughout the project.- Custom Type Files: Can be organized modularly, allowing you to create multiple files for different parts of your application (e.g.,
user.types.ts
,product.types.ts
).
- Usage:
env.d.ts
: Automatically included in the TypeScript compilation, no need to import types declared here.- Custom Type Files: Types must be explicitly imported where they are used, promoting clearer dependencies and better modularization.
Example of Using Both Approaches:
-
env.d.ts for Environment Variables:
// env.d.ts declare namespace NodeJS { interface ProcessEnv { NEXT_PUBLIC_API_URL: string; NEXT_PUBLIC_ANALYTICS_ID: string; } }
-
types/user.types.ts for Custom Types:
// types/user.types.ts export interface User { id: number; name: string; email: string; } export type UserRole = 'admin' | 'user' | 'guest';
-
Including env.d.ts in tsconfig.json:
// tsconfig.json { "compilerOptions": { // other options }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "env.d.ts"], "exclude": ["node_modules"] }
-
Using Custom Types in a Component:
// app/page.tsx import { User, UserRole } from '../types/user.types'; const HomePage = () => { const user: User = { id: 1, name: 'John Doe', email: '[email protected]' }; const role: UserRole = 'admin'; return ( <div> <h1>Welcome, {user.name}</h1> <p>Your role is: {role}</p> </div> ); }; export default HomePage;
Summary
Using env.d.ts
is ideal for global type declarations and environment variables, while defining custom types in separate files is better for modularity and maintainability of your application’s specific types. Both approaches can be used in conjunction to achieve a well-organized and type-safe codebase in a Next.js TypeScript project. For creating app specific types, read this blog.