npm install -D typescript
@types/node @types/react
@types/express
npx tsc --init
// tsconfig.json (key settings)
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"strict": false,
// ↑ Start lenient, tighten later
"allowJs": true,
// ↑ JS and TS coexist
"jsx": "react-jsx",
"outDir": "./dist",
"rootDir": "./src",
"esModuleInterop": true,
"resolveJsonModule": true,
"skipLibCheck": true,
},
"include": ["src/**/*"],
}
// types/models.ts
export interface User {
id: string;
name: string;
email: string;
createdAt: Date;
role: 'user' | 'admin';
}
export interface Image {
id: string;
title: string;
owner: string; // User.id
originalPath: string;
thumbnailPath?: string;
// ↑ ? means optional
width: number;
height: number;
fileSize: number;
format: 'jpeg' | 'png'
| 'webp' | 'gif';
status: 'processing'
| 'ready' | 'failed';
createdAt: Date;
}
export interface Filter {
name: string;
type: 'convolution'
| 'colorMatrix' | 'custom';
kernel?: number[];
matrix?: number[];
params?: Record<string, number>;
}
export interface EditorState {
currentImage: Image | null;
activeFilter: Filter | null;
history: ImageData[];
historyIndex: number;
zoom: number;
isDirty: boolean;
}
// filters.ts (was filters.js)
export function applyConvolution(
imageData: ImageData,
kernel: number[]
): ImageData {
const { data, width, height }
= imageData;
const output =
new Uint8ClampedArray(data);
const kSize =
Math.sqrt(kernel.length);
// TS catches: kernel.length must
// be a perfect square (3×3 or 5×5)
if (kSize % 1 !== 0) {
throw new Error(
'Kernel must be square');
}
// ... rest of convolution
return new ImageData(
output, width, height);
}
export function applyColorMatrix(
imageData: ImageData,
matrix: number[]
): ImageData {
if (matrix.length !== 9) {
// TS + runtime check
throw new Error(
'Color matrix must have 9 values');
}
// ...
return imageData;
}
// BUG 1: Wrong argument type
// ❌ Was: passing string to number param
applyVignette(imageData, "0.5");
// TS error: Argument of type 'string'
// is not assignable to type 'number'
// ✅ Fix:
applyVignette(imageData, 0.5);
// BUG 2: Accessing undefined property
// ❌ Was: image.thumbnail (wrong name)
const url = image.thumbnail;
// TS error: Property 'thumbnail' does
// not exist on type 'Image'.
// Did you mean 'thumbnailPath'?
// ✅ Fix:
const url = image.thumbnailPath;
// BUG 3: Missing function argument
// ❌ Was: called with 1 arg, needs 2
applyConvolution(imageData);
// TS error: Expected 2 arguments,
// but got 1.
// ✅ Fix:
applyConvolution(imageData, kernel);
git switch -c feature/PIXELCRAFT-075-typescript-intro
git add src/ types/ tsconfig.json
git commit -m "Convert 5 critical files to TypeScript, fix 3 bugs (PIXELCRAFT-075)"
git push origin feature/PIXELCRAFT-075-typescript-intro
# PR → Review → Merge → Close ticket ✅
Type systems are the most effective bug prevention tool in software engineering.
Studies show that ~15% of JavaScript bugs could be caught by TypeScript at compile time — before a single line of code runs.