← Back to TypeScript Course | Chapter 27: Migration from JavaScript | Lesson 6 of 6

Common Migration Issues

Migration can expose implicit any values, incompatible libraries, module differences, and incorrect assumptions in existing JavaScript. Understanding these issues makes conversion smoother.
Syntax
typescript
// tsconfig.json
{
  "compilerOptions": { "noImplicitAny": true }
}

function functionName(param: ParamType): ReturnType {
    // ...
}

Core Concept

The most common early migration issue is implicit any everywhere — function parameters and variables with no inferable type default to any unless noImplicitAny is on, silently defeating the whole point of migrating.

Example: Core Concept

typescript
function process(value) { // implicit any without noImplicitAny
  return value;
}
console.log(process(5));

Basic Setup

A basic fix pattern: enable noImplicitAny early even before full strict mode, since it's the single flag that surfaces the most "this needs an actual type" locations across a freshly-migrated codebase.

Example: Basic Setup

typescript
// tsconfig.json: { "compilerOptions": { "noImplicitAny": true } }
console.log("noImplicitAny surfaces every location needing a real type");

Typed Example

A typed example of a classic gotcha: a function that sometimes returns null and sometimes an object will silently type as the object shape unless strictNullChecks is on, hiding a real runtime null-check bug until it crashes in production.

Example: Typed Example

typescript
function findUser(id: number): { name: string } | null {
  return id === 1 ? { name: "Ravi" } : null;
}
const user = findUser(2);
// Without strictNullChecks, user.name would compile but crash at runtime.
if (user) console.log(user.name);

Project Usage

In a real project, third-party libraries without type definitions are a frequent blocker — either a @types/<package> package needs installing, or a local .d.ts declaration has to be hand-written to unblock the migration.

Example: Project Usage

typescript
// npm install --save-dev @types/lodash
// or write a local declare module "untyped-lib" { ... } block.
console.log("Untyped third-party libraries often block migration progress");

Best Practices

Resist the urge to sprinkle // @ts-ignore to silence every migration-era error — each one is a spot the type checker found a real potential bug, and suppressing it just defers the problem instead of fixing it.

Example: Best Practices

typescript
function risky(value: unknown) {
  // Avoid: // @ts-ignore
  // Prefer narrowing the actual value instead of suppressing the error:
  if (typeof value === "string") console.log(value.toUpperCase());
}
risky("hello");
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Leaving function parameters untyped, like function process(value), which silently become any unless noImplicitAny is on.
  2. Adding // @ts-ignore or as any to every error instead of fixing the underlying types.
  3. Importing a JavaScript library with no types and getting Could not find a declaration file, when you need @types/<package> or a declare module line.
Chapter Summary
  • A migration strategy lets you move a JavaScript project to TypeScript step by step.
  • The allowJs and checkJs options and JSDoc type annotations add type checking to existing JavaScript files.
  • Gradual migration helps you handle common migration issues without rewriting everything at once.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.