One of the things I love about TypeScript is that it doesn’t force you to start from scratch. You can adopt it gradually in existing JavaScript projects without breaking everything at once. Over the years, I’ve helped teams migrate large codebases step by step, and the payoff has always been worth it—fewer bugs, clearer contracts, and a more confident development workflow. In this chapter, we’ll go over practical strategies to bring TypeScript into your JavaScript projects, work with third-party libraries, and write your own type declarations when needed.
1. Getting Started: Adding TypeScript to an Existing JavaScript Project
Install TypeScript and dependencies:
npm install --save-dev typescript @types/node
Initialize TypeScript configuration:
npx tsc --init
This generates a tsconfig.json
file. Start with the defaults, then refine it as your project grows.
Rename files gradually:
Change a few files from .js
to .ts
(or .tsx
for React). TypeScript and JavaScript can coexist, so you don’t need to migrate everything at once.

2. Migration Strategies for JavaScript to TypeScript
allowJs: In your tsconfig.json
, enable JavaScript support:
{ "allowJs": true, "checkJs": false }
This allows .js
and .ts
files to work together.
Use JSDoc for gradual typing: Annotate JavaScript with JSDoc comments to get type checking without renaming files.
/** @param {number} x */ function square(x) { return x * x; }
- Fix errors incrementally: Start with looser settings (e.g.,
strict: false
) and tighten them as you gain confidence. - Refactor to strengthen types: As files migrate, replace implicit types with explicit ones using interfaces and type aliases.
3. Using Third-Party Libraries with TypeScript
DefinitelyTyped & @types packages: Many libraries ship with type definitions via @types/*
.
npm install --save-dev @types/lodash
When types are missing: Write a minimal declaration file:
// types/my-library.d.ts declare module 'my-untyped-lib';
Use this sparingly—only when no types exist.
4. Writing Your Own Type Declarations
Custom modules and globals:
// global.d.ts declare module 'my-cool-lib' { export function awesome(): void; }
Typing complex objects with interfaces:
interface Config { apiUrl: string; retryAttempts?: number; }
5. Migrating React Projects to TypeScript
- Rename files from
.js
to.tsx
. - Add types for props and state.
- Use
React.FC<Props>
or explicit annotations.
type ButtonProps = { label: string; onClick: () => void; }; const Button: React.FC<ButtonProps> = ({ label, onClick }) => ( <button onClick={onClick}>{label}</button> );
6. Best Practices for Migration
- Commit often—keep changes small and manageable.
- Leverage editor tooling (VS Code, WebStorm) for instant feedback.
- Enable
strict
mode once your project stabilizes. - Update build/test scripts to include TypeScript.
7. Troubleshooting Common Migration Issues
- Missing types: Search npm for
@types/*
or write custom declarations. - Ambiguous
any
warnings: Gradually replaceany
with proper types. - Third-party JavaScript: Isolate untyped modules and add types later.
- Complex tsconfig.json: Use official TypeScript docs as a guide.
Quick Recap
- Adopt TypeScript incrementally—no big rewrite required.
- Use type declarations (
@types
,.d.ts
files) for third-party and legacy code. - Strengthen types gradually, tightening checks as you progress.
- Let TypeScript’s tooling help you catch errors early and boost confidence.
Coming up next: Real-World TypeScript with React & Next.js—supercharge your modern frontends with type safety and an improved developer experience.