A command-line tool that generates production-ready Express projects with TypeScript built in. Spin up a web server in seconds that follows the TypeScript best practices.
· · ·
express-generator-typescript works like the classic express-generator package, but the project it creates is fully set up for TypeScript. You get strict typing, linting, hot reloading, and testing, with defaults aimed at APIs and no build step. The project is an ES module and comes with a #src/* import alias, so imports stay clean as the app grows.
· · ·
- TypeScript-first – strict compiler settings, linting, and sensible tsconfig defaults, ready to go.
- Built for APIs – ideal for SPAs, mobile backends, or services.
- Fast development – runs TypeScript directly with Node's built-in type stripping (no build step, in development or production), restarts the server when you change it, and refreshes the browser when you change front-end files. Node's built-in test runner and ESLint are included.
- Path aliases – import from
#src/*anywhere. It works in development, tests, and production. - Lean dependencies – no view engine, ORM, or UI layer; only the essentials for Express + TypeScript.
· · ·
Requires Node.js 22.18+ (22.x), 24.x, or 26+.
npx express-generator-typescript
# or install globally
npm install -g express-generator-typescript· · ·
# generate a project (defaults to express-gen-ts)
npx express-generator-typescript my-api
cd my-api
# start developing at http://localhost:3000
npm run dev· · ·
| Option | Description |
|---|---|
project name |
Folder to create. Defaults to express-gen-ts. |
--use-yarn |
Install dependencies with Yarn instead of npm. |
--force |
Write into a folder that isn't empty. Files with the same name are overwritten. |
-h, --help |
Show usage. |
-v, --version |
Show the generator version. |
Without
--force, the generator won't write into a folder that already has files in it, so it can't overwrite your work by accident.
· · ·
The generated project is a small CRUD app for a User record. It shows how to structure models, services, and routes in Express + TypeScript. Linting, formatting, testing, and hot reloading are all set up for you.
npm run dev– Run the server in development with live reload and browser refresh.npm test– Run the tests with Node's built-in test runner.npm test -- tests/users.test.ts– Run a single test file.npm run lint– Check the code with ESLint.npm run format– Format the code with Prettier.npm start– Run the server in production mode (no build step).npm run typecheck– Check for TypeScript errors.npm run install:clean– Deletenode_modulesand the lockfile, then reinstall.
The app uses a layered architecture, which suits a small CRUD app. If you plan to grow it, consider switching to a domain-based layout. The Typescript Best Practices README explains both patterns.
Layers explained:
- config/ → .env files for each environment
- src/ → Source code
- common/ → Shared code
- classes/ → Shared classes (e.g. route errors)
- constants/
- Paths.ts → Single source of truth for all API routes
- types/ → Shared types
- utils/ → Shared helper functions
- entities/ → Describe and handle database records (one folder per entity)
- routes/ → Read and validate values from Express requests; send responses
- services/ → Business logic (where everything comes together)
- repos/ → Talk to the database
- public/ → Front-end scripts and styles
- views/ → HTML pages
- main.ts → Starts the server
- server.ts → Sets up the Express app
- tests/ → Tests· · ·
Format on save
The generated project uses ESLint for linting and Prettier for formatting. To format on save, install the Prettier extension for VS Code and set it as the default formatter in .vscode/settings.json:
// .vscode/settings.json
{
"editor.minimap.enabled": false,
"editor.rulers": [80],
"editor.tabSize": 2,
"workbench.sideBar.location": "right",
"workbench.editor.empty.hint": "hidden",
// Formatting: Prettier only
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
// ESLint: linting only (NO formatting)
"eslint.format.enable": false,
"eslint.nodePath": "node_modules",
"eslint.validate": ["javascript", "typescript", "typescriptreact"],
// Run ESLint fixes (non-formatting) on save
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
// Language overrides (keep Prettier)
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// JSDoc noise reduction
"javascript.suggest.completeJSDocs": false,
"javascript.suggest.jsdoc.generateReturns": false,
"typescript.suggest.completeJSDocs": false,
"typescript.suggest.jsdoc.generateReturns": false
}Debugging
To debug with breakpoints in VS Code, start the app or tests from .vscode/launch.json:
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Dev",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
},
{
"name": "Test",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "test"],
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
}
]
}· · ·
MIT © seanpmaxwell1
