How to Set Up a TypeScript Project from Scratch
Create a TypeScript project from scratch: tsconfig.json, strict mode, and build scripts. A hands-on setup guide for Node.js and TypeScript.
Why strict mode from day one
TypeScript’s value is catching mistakes before runtime — but only if strict is
on. Turning it on later means fixing a wall of errors at once. Enable it now,
when there’s no legacy code to migrate.
Step 1 — Initialize the project
mkdir my-ts-project && cd my-ts-project
npm init -y
npm install -D typescript tsx @types/node
typescript— the compiler.tsx— runs.tsfiles directly during development.@types/node— types for Node’s standard library.
Step 2 — Create tsconfig.json
npx tsc --init
Replace the generated file with a focused config:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"noUncheckedIndexedAccess": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}
noUncheckedIndexedAccess makes array/object access return T | undefined,
forcing you to handle missing keys explicitly.
Step 3 — Write your first module
src/index.ts:
interface Greeting {
name: string;
punctuation?: string;
}
export function greet(input: Greeting): string {
const mark = input.punctuation ?? "!";
return `Hello, ${input.name}${mark}`;
}
console.log(greet({ name: "devnotes" }));
Step 4 — Add build and dev scripts
In package.json:
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
}
npm run dev hot-reloads during development; npm run build typechecks and
emits plain JavaScript to dist/.
Step 5 — Wire typechecking into CI
Make type errors fail the build:
npm run build
tsc with strict is your first line of defense — treat any error as a bug,
not a suggestion.
Troubleshooting
Cannot find modulewith ESM — with"module": "NodeNext", local imports need explicit.jsextensions (import { greet } from "./index.js").Object is possibly undefined— that’sstrict/noUncheckedIndexedAccessdoing its job; narrow with a guard or optional chaining.- Output directory is messy — confirm
rootDir/outDirare set sotscmirrors yoursrc/layout.
Summary
You have a strict, modern TypeScript project with a dev loop (tsx watch) and a
production build (tsc). The compiler is now guarding every commit.
Comments
One comment per thread every 30 minutes · edits are unlimited.
Signed in as devnotes-admin — this will post under your admin identity.