TypeScript adoption fails when teams try to migrate everything at once. The correct strategy is incremental — enable TypeScript alongside JavaScript, add types gradually, tighten strictness over time. This guide covers the migration path that actually works in production codebases, the tsconfig settings in the right order, and the utility types that replace the most common any escapes.
⚡ TL;DR: Start with allowJs + checkJs to get errors without rewriting. Rename .js to .ts one file at a time. Enable strict flags one by one. Use unknown over any. Master Partial, Required, Pick, Omit, Record, ReturnType, and Parameters — they replace 80% of any usage.
Step 1: Add TypeScript without breaking anything
// tsconfig.json — start permissive, tighten gradually
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"allowJs": true, // Let TypeScript coexist with JavaScript
"checkJs": false, // Don't error on .js files yet
"strict": false, // Start permissive
"noImplicitAny": false, // Allow implicit any for now
"outDir": "./dist",
"rootDir": "./src",
"sourceMap": true,
"declaration": true
},
"include": ["src/**/*"]
}
// At this stage: TypeScript compiles but doesn't complain
// Rename files from .js to .ts one at a time as you add typesStep 2: Enable strict flags one at a time
// Enable in this order (each catches a different bug class):
// Week 1: noImplicitAny — catch untyped parameters
// "noImplicitAny": true
// Error: function add(a, b) { return a + b; } — a and b need types
// Week 2: strictNullChecks — catch null/undefined bugs
// "strictNullChecks": true
// Error: const name = user.getName(); name.toUpperCase();
// user.getName() might return null!
// Week 3: strictFunctionTypes — catch callback type mismatches
// "strictFunctionTypes": true
// Week 4: strict: true — enables all remaining strict checks
// "strict": true
// Includes: strictBindCallApply, strictPropertyInitialization, noImplicitThis
// Final: tighten further
// "noUncheckedIndexedAccess": true -- arr[i] returns T | undefined
// "exactOptionalPropertyTypes": true -- explicit vs missing propertiesUtility types that replace any
interface User { id: number; name: string; email: string; createdAt: Date; }
// Partial — all properties optional (update payloads)
type UpdateUser = Partial; // { id?: number; name?: string; ... }
// Required — all properties required (reverse Partial)
type RequiredUser = Required>;
// Pick — select specific properties
type UserPreview = Pick; // { id: number; name: string }
// Omit — exclude specific properties
type UserWithoutDates = Omit;
// Record — typed object/map
type RolePermissions = Record<'admin' | 'user' | 'guest', string[]>;
// ReturnType — extract function return type
type ApiResponse = ReturnType; // Inferred from function
// Parameters — extract function parameter types
type FetchParams = Parameters; // [id: string, options?: Options]
// Awaited — unwrap Promise type
type ResolvedUser = Awaited>; // User, not Promise unknown vs any — always prefer unknown
// any: opt out of type checking — dangerous
function bad(value: any) {
value.toUpperCase(); // No error! Crashes at runtime if value is number
}
// unknown: must narrow before use — safe
function good(value: unknown) {
// value.toUpperCase(); // Error: unknown has no methods
if (typeof value === 'string') {
value.toUpperCase(); // Now TypeScript knows it's a string
}
}
// Use unknown for:
// - Function parameters you don't control (API responses, event handlers)
// - JSON.parse() return value (always returns any — cast to unknown first)
const raw: unknown = JSON.parse(apiResponse);
// Now narrow with type guard before usingTypeScript migration checklist
- ✅ Add TypeScript with allowJs: true — migrate files incrementally
- ✅ Enable strict flags one per week — each week fixes a new bug class
- ✅ Use unknown instead of any for external data
- ✅ Master utility types — they replace most any usage
- ✅ Add @ts-check comment to .js files for gradual type checking
- ✅ Use // @ts-ignore sparingly with a comment explaining why
- ❌ Never use any to silence TypeScript — it defeats the purpose
- ❌ Never migrate an entire codebase at once — incremental only
TypeScript migration builds on the TypeScript generics deep dive — once you’ve migrated, generics are the next major unlock. External reference: TypeScript official migration guide.
Free Weekly Newsletter
🚀 Don’t Miss the Next Cheat Code
Related: JavaScript Prototype Chain: How Inheritance Really Works in JS · JavaScript Closures, Scope, and the Module Pattern: The Complete Guide · JavaScript Promises: The Complete Guide From Basics to Advanced Patterns
Related: JavaScript Async/Await: Every Pattern, Pitfall, and Performance Trick · How HTTPS Works: TLS, Certificates, and Encryption Explained for Developers · OAuth 2.0 and JWT Explained: How Authentication Actually Works in Production
Watch: 100 Days of AI on YouTube
Short videos from CheatCoders, one AI engineering topic per day.
Most viewed
- Python Decorators Explained: From Simple Wrappers to Production Patterns
- Claude Code vs Cursor vs GitHub Copilot: Choose by Workflow, and Set Up One Repo That Works With All Three
- AI Agent Frameworks in 2025: LangGraph vs CrewAI vs AutoGen vs Raw API
- Python String Methods: Every str Method With Real Production Examples
- REST API Design Best Practices: The Patterns That Make APIs a Joy to Use
Newly added
- AWS Systems Manager Parameter Store: Hierarchical Runtime Config for Coding Agents
- Amazon Cognito Identity Pools: Federate Coding-Agent Tool Callers Without Long-Lived Keys
- Amazon Athena for Coding Agents: Query Tool Audit Logs and Eval Traces on S3 Without a Warehouse
- AWS Batch for Coding Agents: Parallel Overnight PR Reviews and Long-Running Jobs Without Lambda Timeouts
- Amazon Bedrock Prompt Management: Version and A/B Test Coding-Agent System Prompts
Deep-dive PDF
Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.
Already subscribed? or open the subscribe page.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
