This article is published in English.
React JS to TypeScript Migration Part 1: Safe Project Setup
Strictness flags, tsconfig shape, and module-by-module conversion that keeps the app shipping.
This walkthrough rebuilds an operable path for: Migrating the React App from JavaScript to TypeScript (Part 1): Setup Without Breaking Anything. Focus on contracts, checks, and code you can drop into a repo without guessing intent.
Why you Decided to Migrate
For Why you Decided to Migrate, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Prefer small, testable units over sprawling scripts. When a step fails, the failure should point at a single responsibility rather than a tangled pipeline. Migrate module by module with strictness flags that fail CI on new any usage.
Step 1: Install TypeScript
For Step 1: Install TypeScript, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion. Migrate module by module with strictness flags that fail CI on new any usage.
npm install -D typescript @types/react @types/react-dom @types/node
--save-dev
Why Install Them as Development Dependencies?
For Why Install Them as Development Dependencies?, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Record timings and cost next to functional results. Visibility early prevents surprise bills when the path moves from demo to shared environments. Migrate module by module with strictness flags that fail CI on new any usage.
A simple rule of thumb
For A simple rule of thumb, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Migrate module by module with strictness flags that fail CI on new any usage.
Step 2: Create the TypeScript Configuration
For Step 2: Create the TypeScript Configuration, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Migrate module by module with strictness flags that fail CI on new any usage. For Step 2: Create the TypeScript Configuration, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
npx tsc --init
Step 3: Configure TypeScript for Gradual Migration
For Step 3: Configure TypeScript for Gradual Migration, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Record timings and cost next to functional results. Visibility early prevents surprise bills when the path moves from demo to shared environments. Prefer composition over inheritance for UI surfaces that AI tools will edit later.
{
"allowJs": true,
"checkJs": false,
"noEmit": true
}
What do these options do?
For What do these options do?, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Prefer composition over inheritance for UI surfaces that AI tools will edit later.
Step 4: Migrate main.jsx to main.tsx
For Step 4: Migrate main.jsx to main.tsx, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Prefer composition over inheritance for UI surfaces that AI tools will edit later.
1. CSS Imports
For 1. CSS Imports, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Prefer small, testable units over sprawling scripts. When a step fails, the failure should point at a single responsibility rather than a tangled pipeline. Prefer composition over inheritance for UI surfaces that AI tools will edit later.
import "./index.css";
/// <reference types="vite/client" />
import "./index.css";
import logo from "./logo.svg";
2. Handling Nullable Values
For 2. Handling Nullable Values, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion. Prefer composition over inheritance for UI surfaces that AI tools will edit later.
document.getElementById("root")
HTMLElement | null
document.getElementById("root")!
<div id="root"></div>
const rootElement = document.getElementById("root");
if (rootElement) {
createRoot(rootElement).render(<App />);
}
Why This Approach Worked
For Why This Approach Worked, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Record timings and cost next to functional results. Visibility early prevents surprise bills when the path moves from demo to shared environments. Prefer composition over inheritance for UI surfaces that AI tools will edit later.
What you Learned
For What you Learned, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Prefer composition over inheritance for UI surfaces that AI tools will edit later.
Wrapping Up
For Wrapping Up, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Prefer composition over inheritance for UI surfaces that AI tools will edit later. For Wrapping Up, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
Try PrepFlow
For Try PrepFlow, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Record timings and cost next to functional results. Visibility early prevents surprise bills when the path moves from demo to shared environments. Colocate types with components and keep props narrow. Wide prop bags become the debt that TypeScript was meant to prevent.
Operational checklist
For Operational checklist, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state.
Prefer small, testable units over sprawling scripts. When a step fails, the failure should point at a single responsibility rather than a tangled pipeline.
Colocate types with components and keep props narrow. Wide prop bags become the debt that TypeScript was meant to prevent.
Write a short runbook: how to rotate keys, how to drain the queue, how to roll back the last change.
Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
Colocate types with components and keep props narrow. Wide prop bags become the debt that TypeScript was meant to prevent.
Before promoting the stack, freeze versions, capture a golden transcript for the critical path, and confirm rollback steps. Shared environments need rate limits, tenancy checks, and a clear owner for secret rotation. Prefer boring reliability over clever one-off demos.