Modules & Configuration
Understanding how TypeScript handles modules and project configuration is essential for building real-world applications. This chapter covers ES modules, namespaces, and the all-important tsconfig.json.
1. ES Modules
TypeScript fully supports ES modules (ESM), the standard JavaScript module system.
Named Exports
// utils.ts
export const PI = 3.14159 ;
export function add ( a : number , b : number ) : number {
return a + b ;
}
export function subtract ( a : number , b : number ) : number {
return a - b ;
}
export interface User {
id : number ;
name : string ;
}
export class Calculator {
add ( a : number , b : number ) : number {
return a + b ;
}
}
// main.ts
import { PI , add , subtract , User , Calculator } from './utils' ;
console . log ( PI ); // 3.14159
console . log ( add ( 2 , 3 )); // 5
const user : User = { id: 1 , name: 'Alice' };
const calc = new Calculator ();
Default Exports
// User.ts
export default class User {
constructor ( public name : string , public email : string ) {}
greet () : string {
return `Hello, I'm ${ this . name } ` ;
}
}
// main.ts
import User from './User' ; // No braces for default import
const user = new User ( 'Alice' , '[email protected] ' );
Mixed Exports
// api.ts
export const API_URL = 'https://api.example.com' ;
export const VERSION = '1.0.0' ;
export default class ApiClient {
constructor ( private baseUrl = API_URL ) {}
async get < T >( path : string ) : Promise < T > {
const response = await fetch ( ` ${ this . baseUrl }${ path } ` );
return response . json ();
}
}
// main.ts
import ApiClient , { API_URL , VERSION } from './api' ;
Import Aliases
import { add as sum , subtract as minus } from './utils' ;
console . log ( sum ( 2 , 3 )); // 5
console . log ( minus ( 5 , 2 )); // 3
Namespace Import
import * as utils from './utils' ;
console . log ( utils . PI );
console . log ( utils . add ( 2 , 3 ));
Type-Only Imports
// Only import types (removed at runtime)
import type { User , Config } from './types' ;
// Combined import
import { fetchUser , type User } from './api' ;
// Type-only export
export type { User , Config };
2. Re-exports (Barrel Files)
Create a single entry point for multiple modules.
// models/User.ts
export interface User {
id : number ;
name : string ;
}
// models/Product.ts
export interface Product {
id : number ;
name : string ;
price : number ;
}
// models/index.ts (barrel file)
export { User } from './User' ;
export { Product } from './Product' ;
export * from './Order' ; // Re-export everything from Order
// main.ts
import { User , Product , Order } from './models' ;
Selective Re-exports
// services/index.ts
export { UserService } from './UserService' ;
export { ProductService } from './ProductService' ;
// OrderService is not exported (internal use only)
// Rename on re-export
export { InternalService as ExternalService } from './InternalService' ;
3. Module Resolution
How TypeScript finds imported modules.
Relative Imports
// Relative paths - start with ./ or ../
import { utils } from './utils' ; // Same directory
import { config } from '../config' ; // Parent directory
import { helper } from './lib/helper' ; // Subdirectory
Non-relative Imports
// Node modules
import express from 'express' ;
import { Request , Response } from 'express' ;
// Path aliases (configured in tsconfig)
import { User } from '@models/User' ;
import { api } from '@services/api' ;
Module Resolution Strategies
// tsconfig.json
{
"compilerOptions" : {
// "node" - Node.js style resolution
// "classic" - TypeScript's original resolution (rarely used)
// "node16" / "nodenext" - ESM-aware Node.js resolution
"moduleResolution" : "node"
}
}
4. Declaration Files (.d.ts)
Type definitions for JavaScript libraries.
Using @types Packages
npm install --save-dev @types/node
npm install --save-dev @types/express
npm install --save-dev @types/lodash
Creating Declaration Files
// types/mylib.d.ts
declare module 'mylib' {
export function doSomething ( value : string ) : number ;
export const VERSION : string ;
export interface Options {
debug ?: boolean ;
timeout ?: number ;
}
export default class MyLib {
constructor ( options ?: Options );
process ( data : string ) : string ;
}
}
Ambient Declarations
// globals.d.ts
declare const __DEV__ : boolean ;
declare const __VERSION__ : string ;
declare function gtag ( command : string , ... args : any []) : void ;
declare interface Window {
analytics : {
track ( event : string , data ?: object ) : void ;
};
}
5. Namespaces
TypeScript’s original module system (still useful for type organization).
namespace Validation {
export interface Validator {
isValid ( value : string ) : boolean ;
}
export class EmailValidator implements Validator {
isValid ( value : string ) : boolean {
return / ^ [ ^ \s@ ] + @ [ ^ \s@ ] + \. [ ^ \s@ ] + $ / . test ( value );
}
}
export class PhoneValidator implements Validator {
isValid ( value : string ) : boolean {
return / ^ \d {10} $ / . test ( value );
}
}
}
// Usage
const emailValidator = new Validation . EmailValidator ();
emailValidator . isValid ( '[email protected] ' ); // true
Nested Namespaces
namespace App {
export namespace Models {
export interface User {
id : number ;
name : string ;
}
}
export namespace Services {
export class UserService {
getUser ( id : number ) : Models . User | null {
return null ;
}
}
}
}
// Usage
const user : App . Models . User = { id: 1 , name: 'Alice' };
const service = new App . Services . UserService ();
Prefer ES modules over namespaces for new code. Namespaces are still useful for:
Organizing types in declaration files
Global type augmentation
Legacy codebases
6. tsconfig.json
The TypeScript configuration file. Run tsc --init to generate one.
Essential Options
{
"compilerOptions" : {
// Target JavaScript version
"target" : "ES2022" ,
// Module system for output
"module" : "NodeNext" ,
// How to resolve imports
"moduleResolution" : "NodeNext" ,
// Output directory
"outDir" : "./dist" ,
// Source directory
"rootDir" : "./src" ,
// Enable all strict type checks
"strict" : true ,
// Allow importing .json files
"resolveJsonModule" : true ,
// Ensure consistent casing in imports
"forceConsistentCasingInFileNames" : true ,
// Skip type checking of declaration files
"skipLibCheck" : true ,
// Generate .d.ts files
"declaration" : true ,
// Generate source maps
"sourceMap" : true
},
"include" : [ "src/**/*" ],
"exclude" : [ "node_modules" , "dist" ]
}
Strict Mode Options
{
"compilerOptions" : {
"strict" : true ,
// Or individually:
"noImplicitAny" : true ,
"strictNullChecks" : true ,
"strictFunctionTypes" : true ,
"strictBindCallApply" : true ,
"strictPropertyInitialization" : true ,
"noImplicitThis" : true ,
"useUnknownInCatchVariables" : true ,
"alwaysStrict" : true
}
}
Additional Checks
{
"compilerOptions" : {
"noUnusedLocals" : true ,
"noUnusedParameters" : true ,
"noImplicitReturns" : true ,
"noFallthroughCasesInSwitch" : true ,
"noUncheckedIndexedAccess" : true ,
"exactOptionalPropertyTypes" : true
}
}
Path Aliases
{
"compilerOptions" : {
"baseUrl" : "." ,
"paths" : {
"@/*" : [ "src/*" ],
"@models/*" : [ "src/models/*" ],
"@services/*" : [ "src/services/*" ],
"@utils/*" : [ "src/utils/*" ]
}
}
}
// With path aliases
import { User } from '@models/User' ;
import { fetchUser } from '@services/api' ;
import { formatDate } from '@utils/date' ;
Path aliases require additional configuration in your bundler (Webpack, Vite) or Node.js (tsconfig-paths package).
7. Project References
Split large projects into smaller, independently compiled pieces.
Main tsconfig.json
{
"files" : [],
"references" : [
{ "path" : "./packages/core" },
{ "path" : "./packages/api" },
{ "path" : "./packages/web" }
]
}
Package tsconfig.json
// packages/core/tsconfig.json
{
"compilerOptions" : {
"composite" : true ,
"declaration" : true ,
"declarationMap" : true ,
"outDir" : "./dist" ,
"rootDir" : "./src"
},
"include" : [ "src/**/*" ]
}
// packages/api/tsconfig.json
{
"compilerOptions" : {
"composite" : true ,
"outDir" : "./dist" ,
"rootDir" : "./src"
},
"references" : [
{ "path" : "../core" }
],
"include" : [ "src/**/*" ]
}
Build Command
# Build all projects
tsc --build
# Build with watch
tsc --build --watch
# Clean build
tsc --build --clean
8. Common Configurations
Node.js Backend
{
"compilerOptions" : {
"target" : "ES2022" ,
"module" : "NodeNext" ,
"moduleResolution" : "NodeNext" ,
"outDir" : "./dist" ,
"rootDir" : "./src" ,
"strict" : true ,
"esModuleInterop" : true ,
"skipLibCheck" : true ,
"forceConsistentCasingInFileNames" : true ,
"resolveJsonModule" : true ,
"declaration" : true ,
"declarationMap" : true ,
"sourceMap" : true
},
"include" : [ "src/**/*" ],
"exclude" : [ "node_modules" ]
}
React Frontend
{
"compilerOptions" : {
"target" : "ES2020" ,
"lib" : [ "ES2020" , "DOM" , "DOM.Iterable" ],
"module" : "ESNext" ,
"moduleResolution" : "bundler" ,
"jsx" : "react-jsx" ,
"strict" : true ,
"noEmit" : true ,
"isolatedModules" : true ,
"esModuleInterop" : true ,
"skipLibCheck" : true ,
"forceConsistentCasingInFileNames" : true ,
"resolveJsonModule" : true ,
"allowImportingTsExtensions" : true
},
"include" : [ "src" ]
}
Library
{
"compilerOptions" : {
"target" : "ES2020" ,
"module" : "ESNext" ,
"moduleResolution" : "bundler" ,
"outDir" : "./dist" ,
"rootDir" : "./src" ,
"strict" : true ,
"declaration" : true ,
"declarationMap" : true ,
"sourceMap" : true ,
"esModuleInterop" : true ,
"skipLibCheck" : true
},
"include" : [ "src/**/*" ],
"exclude" : [ "node_modules" , "**/*.test.ts" ]
}
9. Module Augmentation
Extend existing modules and types.
Extending Third-Party Types
// Extend Express Request
declare module 'express' {
interface Request {
user ?: {
id : string ;
role : 'admin' | 'user' ;
};
}
}
// Now TypeScript knows about req.user
import { Request , Response } from 'express' ;
function handler ( req : Request , res : Response ) {
if ( req . user ) {
console . log ( req . user . id );
}
}
Extending Global Types
// Extend Window
declare global {
interface Window {
__INITIAL_STATE__ : {
user : User | null ;
config : AppConfig ;
};
}
}
// Extend Array
declare global {
interface Array < T > {
first () : T | undefined ;
last () : T | undefined ;
}
}
Array . prototype . first = function () {
return this [ 0 ];
};
Array . prototype . last = function () {
return this [ this . length - 1 ];
};
package.json Scripts
{
"scripts" : {
"build" : "tsc" ,
"build:watch" : "tsc --watch" ,
"dev" : "tsx watch src/index.ts" ,
"start" : "node dist/index.js" ,
"typecheck" : "tsc --noEmit" ,
"lint" : "eslint src --ext .ts" ,
"test" : "vitest"
}
}
ESLint Configuration
// eslint.config.js
import eslint from '@eslint/js' ;
import tseslint from 'typescript-eslint' ;
export default tseslint . config (
eslint . configs . recommended ,
... tseslint . configs . recommended ,
{
rules: {
'@typescript-eslint/no-unused-vars' : 'error' ,
'@typescript-eslint/no-explicit-any' : 'warn' ,
'@typescript-eslint/explicit-function-return-type' : 'off'
}
}
) ;
Vitest Configuration
// vitest.config.ts
import { defineConfig } from 'vitest/config' ;
export default defineConfig ({
test: {
globals: true ,
environment: 'node' ,
include: [ 'src/**/*.test.ts' ],
coverage: {
provider: 'v8' ,
reporter: [ 'text' , 'json' , 'html' ]
}
}
}) ;
Summary
Concept Example Named Export export { User }Default Export export default class UserNamed Import import { User } from './User'Default Import import User from './User'Type-only Import import type { User } from './User'Barrel File export * from './module'Declaration File .d.ts filesNamespace namespace App { }Path Aliases "@models/*": ["src/models/*"]Project References "references": [{ "path": "./pkg" }]Module Augmentation declare module 'express' { }
What’s Next?
Congratulations! You’ve completed the TypeScript Crash Course. You now have a solid foundation in:
✅ Type annotations and inference
✅ Functions and generics
✅ Interfaces and type aliases
✅ Classes and OOP patterns
✅ Advanced types and utility types
✅ Modules and configuration
Continue Learning
React + TypeScript Build type-safe React applications with hooks, context, and components.
Node.js + TypeScript Create robust backend APIs with Express, NestJS, or Fastify.
Full-Stack TypeScript End-to-end type safety with tRPC, Prisma, and Next.js.
Advanced Patterns Explore design patterns, dependency injection, and architecture.