DEV Community

Cover image for JavaScript project to TypeScript
ZeeshanAli-0704
ZeeshanAli-0704

Posted on

JavaScript project to TypeScript

When migrating a JavaScript project to TypeScript, the challenges usually fall into technical, organizational, and process-related buckets. Here’s how I’d structure an answer:


🔥 Key Challenges & How to Approach Them

1. Codebase Size & Incremental Migration

  • Challenge: Converting a large JS codebase all at once is risky and unrealistic.
  • Approach:

    • Start small with incremental migration.
    • Rename .js.ts or .tsx gradually.
    • Use allowJs and checkJs in tsconfig.json to support hybrid JS + TS code.
    • Prioritize core modules (like API clients, business logic) first before UI-heavy code.

2. Lack of Type Information

  • Challenge: JavaScript code has no types, so TypeScript can’t infer much.
  • Approach:

    • Use any as a temporary escape hatch, but plan to replace it.
    • Add JSDoc comments in legacy JS files for gradual type checking.
    • Replace dynamic patterns with clear interfaces or types.

3. Third-Party Libraries Without Types

  • Challenge: Many JS libraries don’t ship TypeScript definitions.
  • Approach:

    • Use @types/* packages from DefinitelyTyped (npm install @types/lodash).
    • If missing, write custom .d.ts declaration files.
    • For quick progress: use declare module "library-name"; as a placeholder.

4. Dealing With this and Context

  • Challenge: JS code often abuses this, which TypeScript makes stricter.
  • Approach:

    • Refactor to arrow functions or properly bind context.
    • Define explicit types for this where necessary.

5. Dynamic and Loosely-Typed Patterns

  • Challenge: JavaScript often uses duck typing, dynamic objects, or monkey patching.
  • Approach:

    • Replace with interfaces and union types.
    • Use type guards or unknown instead of any.
    • For dynamic JSON, start with Record<string, unknown> and refine types later.

6. Build & Tooling Updates

  • Challenge: Build pipeline needs to support TypeScript.
  • Approach:

    • Add tsc for type-checking.
    • Update bundlers (Webpack, Vite, or Rollup) to handle .ts/.tsx.
    • Set up eslint + typescript-eslint for linting.

7. Cultural & Team Adoption

  • Challenge: Team members may resist TypeScript or misuse any.
  • Approach:

    • Educate with guidelines & code reviews.
    • Start with looser compiler options ("strict": false) and tighten gradually.
    • Encourage pairing and refactoring sessions to introduce best practices.

🛠️ Migration Strategy (Step-by-Step)

  1. Set up TypeScript config
  • tsconfig.json with allowJs: true, checkJs: true.
  1. Enable gradual checks
  • Start with non-strict mode.
  • Slowly enable "strict", "noImplicitAny", "strictNullChecks".
  1. Rename critical files first
  • Convert business logic modules → .ts.
  • Add interfaces for APIs & models.
  1. Handle external libraries
  • Install @types/*.
  • Write .d.ts for missing ones.
  1. Refactor dynamically typed code
  • Introduce unknown, type guards, enums.
  1. Iterate & enforce via CI/CD
  • Run tsc --noEmit in pipelines for type checking.
  • Add ESLint rules to prevent any.

✅ Example Real-World Migration

Suppose you have a legacy JS API client:

// apiClient.js
export function fetchUser(id) {
  return fetch(`/api/user/${id}`)
    .then(res => res.json());
}
Enter fullscreen mode Exit fullscreen mode

Migrated to TypeScript incrementally:

// apiClient.ts
interface User {
  id: number;
  name: string;
  email: string;
}

export async function fetchUser(id: number): Promise<User> {
  const res = await fetch(`/api/user/${id}`);
  return res.json() as Promise<User>;
}
Enter fullscreen mode Exit fullscreen mode

Now consumers of fetchUser get autocompletion, type safety, and error checking.


🎯 Final Thoughts

Migrating JS → TS is less about a “big bang” and more about gradual adoption:

  • Start small → Convert file by file.
  • Leverage tooling → JSDoc, allowJs, declaration files.
  • Enforce culture → Strict mode over time, reduce any.
  • Payoff → Better maintainability, fewer bugs, stronger contracts.

More Details

Check out the full code of this article on All About Typescript.

Get all articles related to system design:

Hashtag: #SystemDesignWithZeeshanAli

GitHub Repository: SystemDesignWithZeeshanAli

Top comments (0)