Using Intelligent Coding Tools to Fix TypeScript Type Errors

    A practical workflow for using AI coding tools to diagnose and fix TypeScript errors: capture compiler output, identify root causes, apply changes in dependency order, review high-risk edits, and validate the result with compilation, tests, linting, and manual regression checks. The article also covers project structure, architectural boundaries, tool limitations, and ways to measure productivity gains.

    Assume a frontend team uses TypeScript 5.4. After upgrading a shared types package, running npx tsc --noEmit produces 25 errors. The following example demonstrates a complete workflow. The files and numbers are illustrative; real projects should follow their own compiler output.

    How Should an Intelligent Coding Tool Read Compiler Errors?

    First, have the compiler produce a plain-text error list. Avoid sending terminal output with color codes directly to the tool:

    1. npx tsc --noEmit --pretty false > tsc-errors.txt 2>&1

    Each error follows a predictable format: file path(line,column): error code: description. For example:

    1. src/pages/profile.tsx(12,18): error TS2305: Module '"../types/user"' has no exported member 'UserRole'.
    2. src/components/business/UserBadge.tsx(7,22): error TS2339: Property 'role' does not exist on type 'User'.
    3. src/services/userApi.ts(31,5): error TS2322: Type 'string' is not assignable to type 'UserRole'.

    After reading this file, the tool can provide each error and the relevant source context to a model, which generates a proposed fix. The developer reviews and approves the proposal before the tool writes changes to the files.

    How Can You Identify Dependencies Between Errors?

    The three errors above appear in three different files, but they have one root cause: src/types/user.ts does not export UserRole and does not define a role field on User. The failed page import, the component error when reading role, and the API-layer type mismatch all result from the same missing definition.

    Before the fix:

    1. // src/types/user.ts
    2. export interface User {
    3. id: string;
    4. name: string;
    5. }

    After addressing the root cause:

    1. // src/types/user.ts
    2. export type UserRole = "admin" | "member" | "guest";
    3. export interface User {
    4. id: string;
    5. name: string;
    6. role: UserRole;
    7. }

    The tool should update this file first, run tsc again, and then address the remaining errors. In this example, the error count falls from 25 to 9. The remaining nine errors are independent and can be handled individually.

    Three signals are useful when determining dependencies:

    • Does one reported file import another file that also has errors?
    • Do multiple errors reference the same type name?
    • Does fixing one file cause the total error count to drop significantly?

    Some changes require manual approval. Developers should review the following before merging:

    • Changes to exported types in src/types
    • Widening a type to any or using an as assertion
    • Changes to authorization logic under pages/auth

    Other changes can be completed in batches on a separate branch, with each batch limited to one module.

    What Counts as Successful Validation?

    Use the following checklist after the fixes:

    1. npx tsc --noEmit reports zero errors.
    2. npm test passes completely, and tests related to the modified files have not been skipped.
    3. npx eslint src reports no new errors. Enabling @typescript-eslint/no-explicit-any is recommended to prevent the tool from hiding problems with any.
    4. Manually regress critical paths, such as login, role-based permission checks, and order submission.
    5. Review git diff to confirm that unrelated code was not removed or changed accidentally.

    Prepare a rollback plan before the tool starts modifying code. Commit the current state or create a new branch first. If validation fails, switch back to the original branch or use git revert to undo the relevant commit instead of overwriting existing work.

    How Should the Directory Structure Be Organized?

    The directory structure determines how much context the tool can see. The following principles help reduce incorrect fixes:

    • Separate pages by access requirements. Store authenticated pages separately from public pages. When generating route guards, the tool can more clearly determine which pages require identity checks, preventing authorization-related changes from spreading into public pages.
    • Separate layout and business components. Keep structural components such as Header and Sidebar in layout, and place domain-specific components in business. Layout files are then less likely to be modified because of changes to business fields.
    • Centralize types. Store TypeScript types under src/types, with one file for each business domain. The tool can see a complete interface in one place, improving cross-file completion.

    An example structure:

    1. src/
    2. pages/
    3. auth/dashboard.tsx requires authentication
    4. public/home.tsx public page
    5. components/
    6. layout/Header.tsx
    7. business/UserBadge.tsx
    8. types/
    9. user.ts
    10. order.ts
    11. services/
    12. userApi.ts

    How Does Layered Architecture Define the Fix Boundary?

    As a project grows, code can be divided into three layers:

    • Data access, such as services
    • Business logic, such as features or custom hooks
    • Presentation, such as components and pages

    Dependencies should flow downward only. The presentation layer may reference the business layer, and the business layer may reference the data layer. The reverse direction should be prohibited. Tools such as eslint-plugin-boundaries can enforce this rule through lint configuration.

    With these boundaries in place, the scope of a fix becomes clearer. When services/userApi.ts contains a type error, the tool only needs to modify the data layer and related type files. It should not need to change page components. Even if an incorrect change is made, its impact is limited to one layer.

    What Are the Limits of Intelligent Coding Tools?

    Intelligent coding tools are not万能? Need English. “not万能” no. Use not infallible. The following issues still require human judgment:

    • Complex conditional types and nested infer expressions. A tool may generate code that compiles but is difficult to maintain. Developers may need to rewrite it into a clearer structure.
    • Business-semantic errors. Successful compilation does not prove that the logic is correct. For example, an order amount may correctly use the number type, while the tool cannot determine whether the unit is cents or dollars.
    • Shortcut fixes. When an error is difficult to resolve, the tool may write as any or @ts-ignore. These patterns should be prohibited in the tool’s rules and backed up with lint rules.

    How Should the Benefits Be Measured?

    Track four metrics:

    • The error count before and after the fix
    • The number of manual approvals
    • The time required for each fix
    • The number of reverted commits after fixes

    Observe the trend over two or three iterations before drawing conclusions. Do not directly apply metrics from another project, because the benefits depend on project size, error types, and the team’s review practices.

    Summary

    A practical implementation can follow four steps:

    1. Plan the directory structure around access control, layout, and shared types, and introduce layer boundaries where appropriate.
    2. Give the tool the complete tsc output, fix root causes first, and then handle cascading errors.
    3. Require manual review for type changes, authorization logic, and any changes involving any.
    4. Run TypeScript compilation, tests, linting, and regression checks before delivery, while preserving a rollback point.