mcpField
A
allowjs-mixing

allowjs-mixing

github.com/marius-townhouseDevelopment643 installsUpdated 38w ago
Repository

About allowjs-mixing

A TypeScript migration guide for teams moving an existing JavaScript project incrementally. It explains how `allowJs` supports mixed `.js` and `.ts` files while modules are converted over time.

Key features

  1. 01Enable mixed JavaScript and TypeScript files
  2. 02Convert modules incrementally
  3. 03Start with dependency leaf modules
  4. 04Import between JavaScript and TypeScript
  5. 05Add types to JavaScript with JSDoc

Use cases

  1. 01Migrating a large JavaScript codebase
  2. 02Adopting TypeScript without a full rewrite
  3. 03Maintaining feature work during migration

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill allowjs-mixing

After installing, type/allowjs-mixingin Claude Code to confirm it loaded.

Details

From the project README

Use allowJs to Mix TypeScript and JavaScript

Overview

Migrating a large JavaScript codebase to TypeScript doesn't have to be all-or-nothing. The allowJs compiler option lets you gradually adopt TypeScript by mixing .ts and .js files in the same project. This enables incremental migration, allowing teams to convert files one at a time while maintaining a working codebase.

This approach is essential for large migrations where a big-bang rewrite isn't feasible.

When to Use This Skill

  • Migrating JavaScript projects to TypeScript
  • Gradually adopting TypeScript in a JS codebase
  • Working with mixed TypeScript/JavaScript teams
  • Converting large existing projects
  • Teams still learning TypeScript

The Iron Rule

Use allowJs to enable incremental migration. Convert files module by module, starting from leaf modules and working up the dependency graph.

Detection

Watch for migration challenges:

// Can't migrate because:
- 1000+ JavaScript files
- Team still learning TypeScript
- Can't stop feature development
- Risk of breaking changes

Enabling allowJs

// tsconfig.json
{
  "compilerOptions": {
    "allowJs": true,        // Allow JavaScript files
    "checkJs": false,       // Don't type check JS (optional)
    "outDir": "./dist",
    "strict": true
  },
  "include": ["src/**/*"]
}

Migration Strategy

Phase 1: Enable allowJs
  - Add tsconfig.json with allowJs: true
  - Rename one file to .ts as proof of concept
  - Ensure build still works

Phase 2: Convert leaf modules
  - Start with files that have no dependencies
  - Utilities, helpers, constants
  - Low risk, easy wins

Phase 3: Work up dependency graph
  - Convert files that only depend on converted files
  - Gradually move toward entry points

Phase 4: Convert entry points last
  - Main files, app entry points
  - Most complex, most dependencies

Converting a File

// utils.js (before)
export function formatDate(date) {
  return date.toISOString().split('T')[0];
}

export const PI = 3.14159;
// utils.ts (after)
export function formatDate(date: Date): string {
  return date.toISOString().split('T')[0];
}

export const PI = 3.14159;

Importing Between JS and TS

// app.ts - TypeScript importing JavaScript
import { formatDate } from './utils.js';  // .js extension
// TypeScript trusts the JS (with checkJs: false)

// With types for JS module
declare module './utils.js' {
  export function formatDate(date: Date): string;
  export const PI: number;
}
// legacy.js - JavaScript importing TypeScript
import { User } from './types.ts';  // Works with allowJs
// JS doesn't get type checking, but can import TS

Adding Types to JavaScript

// @ts-check - Enable type checking for this file

/**
 * @param {string} name
 * @param {number} age
 * @returns {string}
 */
function greet(name, age) {
  return `Hello ${name}, you are ${age}`;
}

/** @type {string[]} */
const names = ['Alice', 'Bob'];

/** @typedef {{ x: number, y: number }} Point */

Migration Checklist

// 1. Set up tsconfig.json with allowJs
{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": false,  // Enable later for stricter checking
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true
  }
}

// 2. Start with simple files
// - No dependencies
// - Pure functions
// - Well-tested

// 3. Add types gradually
// - Start with any if needed
// - Refine over time

// 4. Enable strict mode checks incrementally
// - noImplicitAny
// - strictNullChecks
// - strictFunctionTypes

Pressure Resistance Protocol

When migrating:

  1. Enable allowJs first: Get the infrastructure working
  2. Start small: Convert one file, ensure build works
  3. Prioritize leaf modules: Fewer dependencies = easier
  4. Use any initially: Can refine types later
  5. Track progress: Celebrate small wins

Red Flags

Anti-PatternProblemSolution
Big-bang rewriteToo risky, takes too longIncremental with allowJs
Converting entry points firstToo many dependenciesStart with leaves
No tsconfig.jsonCan't control compilationSet up properly
Abandoning midwayWasted effortTrack and celebrate progress

Common Rationalizations

"We need to convert everything at once"

Reality: Incremental migration with allowJs is safer and more practical for large codebases.

"Mixed JS/TS is confusing"

Reality: It's temporary and manageable. Clear migration plan keeps it organized.

"We'll just keep using JS"

Reality: TypeScript's benefits compound over time. Start small and grow.

Quick Reference

StepActionTimeline
1Add tsconfig with allowJsDay 1
2Convert 1-2 utility filesWeek 1
3Convert leaf modulesWeeks 2-4
4Work up dependency graphMonths 1-3
5Convert entry pointsMonths 3-6
6Remove allowJs (optional)When done

The Bottom Line

Use allowJs for incremental TypeScript adoption. Convert files gradually, starting from leaf modules. This makes large migrations manageable without stopping development.

Reference

  • Effective TypeScript, 2nd Edition by Dan Vanderkam
  • Item 81: Use allowJs to Mix TypeScript and JavaScript

Comments

Markdown supported