npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@obiemunoz/ts-migrate-plugins

v0.10.3

Published

Set of codemods, which are doing transformation of js/jsx to ts/tsx. Maintained fork of airbnb/ts-migrate, updated for TypeScript 5+.

Readme

@obiemunoz/ts-migrate-plugins

ts-migrate-plugins is designed as a set of plugins, so that it can be pretty customizable for different use-cases. This package contains a set of codemods (plugins), which are doing transformation of js/jsx -> ts/tsx.

This is a maintained fork of airbnb/ts-migrate, updated for TypeScript 5 and 6. Original work © 2020 Airbnb (MIT).

Most users should start with @obiemunoz/ts-migrate, the CLI that drives these plugins. Install this package directly only if you're composing a custom migration pipeline.

ts-migrate-plugins was originally designed around Airbnb projects. Use at your own risk.

Install

Install @obiemunoz/ts-migrate-plugins using npm:

npm install --save-dev @obiemunoz/ts-migrate-plugins

Or pnpm:

pnpm add -D @obiemunoz/ts-migrate-plugins

Usage

import path from 'path';
import { tsIgnorePlugin } from '@obiemunoz/ts-migrate-plugins';
import { migrate, MigrateConfig } from '@obiemunoz/ts-migrate-server';

// get input files folder
const inputDir = path.resolve(__dirname, 'input');

// create new migration config and add ts-ignore plugin with empty options
const config = new MigrateConfig().addPlugin(tsIgnorePlugin, {});

// run migration
const { exitCode } = await migrate({ rootDir: inputDir, config });

process.exit(exitCode);

List of plugins

| Name | Description | | ---- | ----------- | | add-conversions | Add conversions to any ($TSFixMe) in the case of type errors. | | declare-missing-class-properties | Declare missing class properties. | | eslint-fix | Run eslint fix to fix any eslint violations that happened along the way. | | explicit-any | Annotate variables with any ($TSFixMe) in the case of an implicit any violation. | | hoist-arrow-functions | Convert arrow functions that are referenced before their definition into hoisted function declarations. Arrow functions only used after their definition are left alone. | | hoist-class-statics | Hoist static class members into the class body (vs. assigning them after the class definition). | | hoist-declarations | Move a top-level const/let above its first use when it is referenced before its definition and can't be converted into a hoisting function declaration (e.g. an HOC-wrapped component). Only relocates when it is provably safe. | | infer-types | Annotate implicit anys with types TypeScript can infer from usage, so only the truly undeterminable ones fall through to explicit-any. | | jsdoc | Convert JSDoc @param types to TypeScript annotations. | | member-accessibility | Add accessibility modifiers (private, protected, or public) to class members according to naming conventions. | | react-class-lifecycle-methods | Annotate React lifecycle method types. | | react-class-state | Declare React state type. | | react-default-props | Annotate React default props. | | react-inline-imported-prop-types | Copy propTypes objects imported from other modules into the file that assigns them (including spreads of them), carrying over the imports the copied text needs, so react-props converts them structurally like colocated propTypes. Runs before the other React plugins. | | react-props | Convert React prop types to TypeScript type. Imported propTypes objects that react-inline-imported-prop-types could not copy (non-relative modules, non-literal exports, references to module-local values) are typed with InferProps<typeof importedPropTypes> instead. | | react-shape | Convert prop types shapes to TypeScript type. | | strip-ts-ignore | Strip // @ts-ignore. comments | | detect-types-packages | Read-only. Classifies the diagnostics ts-ignore is about to suppress into @types package recommendations (missing, not loaded, outdated, or redundant), reported at the end of the run. Created per run with createTypesPackageDetector() and placed immediately before ts-ignore. | | ts-ignore | Add // @ts-ignore comments for the remaining errors. | | update-import-paths | Re-point relative imports that still say ./foo.js/./foo.jsx after the file was renamed to .ts/.tsx. Drops the extension by default; keeps a .js extension in ESM packages ("type": "module") or with { extension: 'js' }. Imports whose target still exists on disk are left alone. |

What infer-types annotations mean

The function body is the source of truth for its contract. Call-site evidence is used only where it contradicts nothing; it never overrides what the body does:

  • Body evidence wins conflicts. greet(name) { return name.toUpperCase(); } is annotated name: string no matter what callers pass; an improper greet(42) becomes a type error that ts-ignore flags at the call site.
  • Harmless call-site evidence is kept. logId(id) { console.log(id); } called only with numbers infers id: number; a setter infers its parameter from consistent assignments.
  • Contradictory or missing evidence falls back to any ($TSFixMe). Call sites that disagree with each other on an unconstrained body, or a body TypeScript cannot express a type for (a + b with mixed callers), get no annotation rather than an arbitrary or suppression-generating one. The plugin never introduces suppressions inside a function body.
  • Members with no evidence are spelled any, not the empty object type or a bottom array type. TypeScript prints a member it knows nothing about as {} (banned by @typescript-eslint/no-empty-object-type) and an empty array literal as never[] (undefined[] without strictNullChecks), which would reject every element later added; initialState = { settings: {}, items: [] } infers settings: any and items: any[]. A genuine undefined[] inferred from real undefined elements under strictNullChecks is kept. An annotation that reduces entirely to any this way is dropped and left to explicit-any, as usual.
  • A signature can still be narrower than everything the function could handle at runtime (half(n) { return n / 2; } infers number even though a numeric string would not crash), and callers the program cannot see (consumers of a published library) contribute no evidence.

Type of plugins

We have two main categories of plugins:

  • Text based plugins. Plugins of this category are operating with a text of source files and operate based on this. Example: example-plugin-text.

  • TypeScript ast-based plugins. The main idea behind these plugins is by parsing Abstract Syntax Tree with TypeScript compiler API, we can generate an array of updates for the text and apply them to the source file. Example: example-plugin-ts.

FAQ

What is a ts-migrate plugin?

The unit of work in the migration pipeline. A plugin gets a file (its text, a parsed ts.SourceFile, and a lazily-created language service for the questions that need type information) and returns the new text of the file. The interface is small on purpose:

interface Plugin {
  name: string
  run(params: PluginParams<TPluginOptions = {}>): Promise<string | void> | string | void
}

interface PluginParams<TPluginOptions = {}> {
  options: TPluginOptions;
  fileName: string;
  rootDir: string;
  text: string;
  sourceFile: ts.SourceFile;
  getLanguageService: () => ts.LanguageService;
}

How do I write my own plugin?

Start with the example plugins, which show the text-based and AST-based approaches side by side, then read the real plugins in this package. My advice: prefer computing text updates from AST node positions over regenerating whole files, since splices preserve the formatting of everything you didn't touch.

Didn't these plugins use jscodeshift?

They did, and honestly that was one of the first things I regretted keeping. The jscodeshift plugins parsed with a babel config frozen around 2018 syntax, so they'd fail on newer JavaScript (class static blocks, for example) or quietly drop type annotations during reprinting. Every plugin now works off the TypeScript AST or plain text splices, so there's exactly one parser involved: the same one that compiles your code. The jscodeshift dependency is gone entirely.

Why does eslint-fix use my project's ESLint instead of bundling one?

Because the point of that step is to make the migrated code pass your lint setup, and only your ESLint install knows your plugins, parser, and rule set. It auto-detects flat versus legacy configs (ESLint 9 included). The flip side: if your config can't parse TypeScript yet, the plugin can't fix those files. It warns once and leaves them unchanged rather than guessing. Unless your config is type-aware (parserOptions.project/projectService, which would multiply TypeScript's memory use per thread), fixes spread across a worker pool once there is enough lint work to repay spinning it up — set TS_MIGRATE_ESLINT_FIX_WORKERS to force a pool size, or 0 to always lint in-process.

I have an issue with a specific plugin, what should I do?

Please file an issue with the smallest input file that reproduces it. Transform bugs get regression tests here, so a good reproduction usually stays fixed for good.

Contributing

See the Contributors Guide.