## Curation Note
TypeScript adoption reached critical mass in 2025, but many teams struggle with migration from existing JavaScript codebases. This skill synthesizes patterns from successful large-scale migrations at companies like Airbnb and Stripe. The gradual adoption strategy (strict mode disabled initially) is crucial because all-or-nothing migrations typically fail. The 4-phase approach has proven effective for teams maintaining production systems during migration.
## Migration Strategy
### Phase 1: Setup & Configuration
```bash
npm install --save-dev typescript @types/node
npx tsc --init
```
```json
// tsconfig.json - Permissive start
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ES2020", "DOM"],
"outDir": "./dist",
"rootDir": "./src",
// Permissive settings for migration
"allowJs": true,
"checkJs": false,
"strict": false,
"noImplicitAny": false,
"skipLibCheck": true
// Enable these gradually
// "strictNullChecks": true,
// "strictFunctionTypes": true,
// "noImplicitAny": true,
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
```
### Phase 2: Rename & Basic Types
```typescript
// 1. Rename .js to .ts (or .jsx to .tsx)
// 2. Fix immediate compilation errors
// 3. Add basic type annotations
// Before (JavaScript)
function processUser(user) {
return {
name: user.name.toUpperCase(),
age: user.age + 1
};
}
// After (TypeScript - minimal types)
interface User {
name: string;
age: number;
}
function processUser(user: User): User {
return {
name: user.name.toUpperCase(),
age: user.age + 1
};
}
```
### Phase 3: Type External Dependencies
```typescript
// For packages without types, create declarations
// src/types/untyped-package.d.ts
declare module 'untyped-package' {
export function doSomething(input: string): Promise<Result>;
export interface Result {
success: boolean;
data: unknown;
}
}
// Or use any temporarily
declare module 'legacy-package' {
const content: any;
export default content;
}
```
### Phase 4: Enable Strict Mode Gradually
```json
// tsconfig.json - Progressive strictness
// Week 1: Enable null checks
"strictNullChecks": true,
// Week 2: Enable implicit any checks
"noImplicitAny": true,
// Week 3: Strict function types
"strictFunctionTypes": true,
// Week 4: Full strict mode
"strict": true,
```
## Common Patterns
### Converting React Components
```typescript
// Before: JavaScript React
function UserCard({ user, onEdit }) {
return (
<div onClick={() => onEdit(user.id)}>
<h2>{user.name}</h2>
</div>
);
}
// After: TypeScript React
interface User {
id: string;
name: string;
}
interface UserCardProps {
user: User;
onEdit: (id: string) => void;
}
function UserCard({ user, onEdit }: UserCardProps) {
return (
<div onClick={() => onEdit(user.id)}>
<h2>{user.name}</h2>
</div>
);
}
```
### Typing API Responses
```typescript
// Define response types
interface ApiResponse<T> {
data: T;
error: string | null;
meta: {
page: number;
total: number;
};
}
interface UserData {
id: string;
name: string;
email: string;
}
// Type the fetch call
async function fetchUsers(): Promise<ApiResponse<UserData[]>> {
const response = await fetch('/api/users');
return response.json();
}
```
### Utility Types for Migration
```typescript
// Partial: Make all properties optional (useful for updates)
type UpdateUser = Partial<User>;
// Pick: Select specific properties
type UserSummary = Pick<User, 'id' | 'name'>;
// Omit: Exclude specific properties
type CreateUser = Omit<User, 'id' | 'createdAt'>;
// Record: Type object with dynamic keys
type UserMap = Record<string, User>;
```
## Best Practices
1. **Start permissive, end strict** - Enable strict flags incrementally
2. **Type boundaries first** - API calls, function signatures, exports
3. **Use inference** - Let TypeScript infer where possible
4. **Avoid `any`** - Use `unknown` and narrow types instead
5. **Create shared types** - Centralize in `/types` directory
6. **Add types to new code** - Enforce TypeScript for new files
7. **Use ESLint TypeScript rules** - Catch type issues early
## Related Resources
- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/)
- [Migrating from JavaScript](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html)