LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1216 min read

Best Practices & Next Steps

Pull together everything you've learned with real-world TypeScript best practices: strict mode, project setup, third-party types, linting, and migration.

Introduction

You've now covered TypeScript's core type system — from basic types through generics, enums, and narrowing. This final lesson focuses on the practical, real-world side: how to configure a project well, work with the wider ecosystem, and where to go from here.

What You Will Learn
  • How to configure and roll out strict mode effectively.
  • How to structure a TypeScript project's tsconfig.json for real work.
  • How to get types for third-party JavaScript libraries.
  • How linting and formatting tools fit alongside the compiler.
  • How to migrate an existing JavaScript codebase to TypeScript gradually.

Configuring Strict Mode

The single `"strict": true` flag in tsconfig.json actually bundles together a whole family of checks: `strictNullChecks` (null and undefined must be handled explicitly), `noImplicitAny` (every value must have a known type), `strictFunctionTypes`, and several others. Turning strict mode on catches dramatically more real bugs, and it is far easier to start a project strict than to retrofit it onto a large, already-loose codebase later.

Project Structure and tsconfig

A well-organized tsconfig.json typically separates source from compiled output using `rootDir` and `outDir`, limits compilation scope with `include`/`exclude`, and can define path aliases so imports like `@/components/Button` resolve cleanly instead of long relative paths like `../../../components/Button`.

{
"compilerOptions": {
"strict": true,
"target": "ES2020",
"rootDir": "src",
"outDir": "dist",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}

Working with Third-Party Types

Many npm packages ship their own type declarations (.d.ts files) built in, so importing them just works with full autocomplete. For older or plain-JavaScript-only packages, the community-maintained DefinitelyTyped project publishes matching type packages under the `@types/` scope.

# For a library without built-in types
npm install --save-dev @types/lodash

Linting and Formatting

The TypeScript compiler checks types, but doesn't enforce style or catch every code-quality issue. ESLint with the `@typescript-eslint` plugin adds type-aware linting rules (like flagging unused variables or unsafe `any` usage), while Prettier handles automatic code formatting — the two are commonly used together, running alongside `tsc` in CI.

TypeScript with Frameworks

React components are typically written in `.tsx` files, typing props with an interface. Next.js has TypeScript support built in with zero configuration. Node.js backends add `@types/node` (and `@types/express` for Express) for full typings of the runtime and framework APIs. Angular is TypeScript-first by design, and modern runtimes like Deno and Bun understand TypeScript natively, with no separate compile step required during development.

interface ButtonProps {
label: string;
onClick: () => void;
}
function Button({ label, onClick }: ButtonProps) {
return <button onClick={onClick}>{label}</button>;
}

Migrating JavaScript to TypeScript

You do not need to convert an entire codebase at once. The standard approach is incremental: enable `allowJs` and `checkJs` so TypeScript can type-check plain .js files using JSDoc comments, then rename files from .js to .ts one at a time, starting with the most-used, most-stable modules. Many teams start with a looser tsconfig on legacy code, then tighten `strict` settings gradually as more of the codebase is converted.

Common Mistakes

Avoid These Mistakes
  • Enabling every strict flag on a large legacy codebase all at once, producing thousands of errors instead of migrating incrementally.
  • Reaching for `@ts-ignore` to silence a compiler error instead of understanding and fixing the actual underlying issue.
  • Skipping `@types/*` packages for third-party JavaScript libraries, quietly losing type safety at every call into that library.
  • Never actually running `tsc --noEmit` in CI, treating TypeScript as documentation rather than an enforced, automated check.

Best Practices

  • Run `tsc --noEmit` in CI so type errors block a merge, exactly like a failing test would.
  • Keep `@types/*` packages updated alongside the libraries they describe.
  • Adopt strict mode as early as possible — even mid-migration, new files can be strict while older files are grandfathered in.
  • Treat compiler complaints as a collaborator catching a real bug, not an obstacle to silence.

Frequently Asked Questions

Practice TypeScript inside a real framework — React with .tsx, Next.js, or Node with Express — and get comfortable with the utility types (Partial, Pick, Omit, Record) covered in the generics lesson.

No — if a library ships its own .d.ts files (increasingly the norm), you get full types automatically with no extra install.

Yes — that is the standard, recommended approach: enable allowJs, rename files incrementally, and tighten strict checks over time rather than converting everything at once.

Yes — most professional frontend and Node.js backend roles today expect TypeScript, and it catches an enormous class of real bugs before they ever reach production.

Key Takeaways

  • `"strict": true` bundles the checks that catch the most real bugs — enable it from day one on new projects.
  • A well-structured tsconfig.json separates source and output and can define clean import path aliases.
  • @types/* packages from DefinitelyTyped provide types for JavaScript-only libraries.
  • ESLint (with @typescript-eslint) and Prettier complement, rather than replace, the TypeScript compiler.
  • Large JavaScript codebases can migrate to TypeScript incrementally, file by file, without a risky rewrite.

Summary

Congratulations — you've completed the TypeScript course, from what TypeScript is and why Microsoft built it, through the full type system, object-oriented programming, generics, and now real-world project practices. The best next step is to build something real: add TypeScript to a small project, turn on strict mode, and let the compiler guide you as you go.