{"id":13683734,"url":"https://github.com/grubersjoe/reflow","last_synced_at":"2025-04-28T16:02:59.838Z","repository":{"id":57188892,"uuid":"174324760","full_name":"grubersjoe/reflow","owner":"grubersjoe","description":"Convert a Flow typed codebase to TypeScript (Babel plugin)","archived":false,"fork":false,"pushed_at":"2021-08-30T15:30:07.000Z","size":1361,"stargazers_count":35,"open_issues_count":5,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-23T06:06:06.977Z","etag":null,"topics":["babel","flow","migration","plugin","transpiler","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grubersjoe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-07T10:41:03.000Z","updated_at":"2025-01-24T22:37:30.000Z","dependencies_parsed_at":"2022-08-28T12:51:40.092Z","dependency_job_id":null,"html_url":"https://github.com/grubersjoe/reflow","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grubersjoe%2Freflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grubersjoe%2Freflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grubersjoe%2Freflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grubersjoe%2Freflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grubersjoe","download_url":"https://codeload.github.com/grubersjoe/reflow/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251342720,"owners_count":21574244,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["babel","flow","migration","plugin","transpiler","typescript"],"created_at":"2024-08-02T13:02:27.348Z","updated_at":"2025-04-28T16:02:59.712Z","avatar_url":"https://github.com/grubersjoe.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Reflow\n\n\u003e Babel plugin to transpile [Flow](https://flow.org/) types to\n\u003e [TypeScript](https://www.typescriptlang.org/) with CLI wrapper.\n\n![Tests](https://github.com/grubersjoe/reflow/workflows/Tests/badge.svg)\n[![Coverage](https://coveralls.io/repos/github/grubersjoe/reflow/badge.svg?branch=master)](https://coveralls.io/github/grubersjoe/reflow?branch=master)\n\n#### I would love to receive feedback whether this plugin worked for you :)!\n\nReflow enables you to migrate a whole Flow based project to TypeScript by\ntranspiling the Flow type annotations to equivalent TypeScript code. While this\nreduces the effort to move a large code base to TypeScript drastically, it is\nstill very likely that you will face new type errors after the migration due to\nthe differences between Flow and TypeScript. See this\n[repository](https://github.com/niieani/typescript-vs-flowtype) for an excellent\noverview of the differences and similarities of Flow and Typescript.\n\n## Why another plugin?\n\nOf course, I am aware that other approaches exist to translate Flow to\nTypeScript. For instance, there is\n[Kiikurage/babel-plugin-flow-to-typescript](https://github.com/Kiikurage/babel-plugin-flow-to-typescript)\nand\n[Khan/flow-to-ts](https://github.com/Kiikurage/babel-plugin-flow-to-typescript).\nWhen I started this project in the course of my master thesis in February 2019,\nthe development of the first plugin seemed inactive and the second one did not\nexist yet. Therefore this plugin was developed to solve the given problem of the\nthesis in practice.\n\n**Advantages of Reflow**\n\n- can be used either as standalone Babel plugin or through the included CLI to\n  transpile whole code bases\n- well tested with high code coverage\n- proven to work with real React based projects (two code bases with 27 and 41\n  kLOC respectively were successfully migrated)\n- generates well formatted output based on Prettier with focus on placing\n  comments at the correct position (Babel fails to do so)\n\n## Installation\n\n```\nyarn add --dev babel-plugin-reflow\n```\n\n## Usage\n\n### CLI\n\nThis package includes a small CLI wrapper for the Babel plugin to recursively\ntranspile whole directories or single files. Install the package as project\ndependency and run `npx reflow` afterwards. Alternatively you might want to\ninstall Reflow globally so you can simply type `reflow`:\n\n```shell\nyarn global add babel-plugin-reflow\n```\n\nUsage is as follows:\n\n```shell\n$ npx reflow --help\n\nUsage: reflow [OPTION]... \u003cFILES OR DIRECTORIES ...\u003e\n\nREFLOW - Flow to TypeScript converter\n\nOptions:\n  -v                                Output the version number\n  -d, --dry-run                     Perform a trial run printing to stdout instead of writing a file\n  -e, --exclude-dirs \u003cpattern ...\u003e  Comma-separated list of directories to recursively exclude (default: [\"node_modules\"])\n  -i, --include-pattern \u003cpattern\u003e   Set the glob pattern for input files (default: \"**/*.{js,jsx}\")\n  -r, --replace                     Process files in-place instead of creating new TS files next to the original JS files\n  -D, --replace-decorators          Replace class @decorators with wrapped function calls to avoid TypeScript errors (default: false)\n  -h, --help                        Output ussage information\n\nExamples:\n  $ reflow --replace src/\n  $ reflow -d -i '**/__tests__/**/*.{js,jsx}' src/\n  $ reflow -exclude-patterns '**/__tests__/**/*','fixtures/*.js' src/\n```\n\n### Programmatically\n\nTODO\n\n### As Babel plugin\n\nTODO\n\n## Transformations\n\n### Base types\n\nSome Flow types are not equivalently expressible in TypeScript. See the list of\nunsupported Flow features below.\n\n| Type                    | Flow                           | TypeScript                           |\n| ----------------------- | ------------------------------ | ------------------------------------ |\n| Any type                | `any`                          | `any`                                |\n| Array type              | `Array\u003cnumber\u003e`                | `Array\u003cnumber\u003e`                      |\n| Boolean literal type    | `true`                         | `true`                               |\n| Boolean type            | `boolean`                      | `boolean`                            |\n| Empty type              | `empty`                        | `never`                              |\n| Exact object type       | `{\\| p: number \\|}`            | `{ p: number }`                      |\n| Function type           | `(string, {}) =\u003e number`       | `(p1: string, p2: {}) =\u003e number`     |\n| Generic type annotation | `let v: \u003cFlowType\u003e`            | `let v: \u003cTSType\u003e`                    |\n| Generics                | `type Generic\u003cT: Super\u003e = T`   | `type Generic\u003cT extends Super\u003e = T`  |\n| Interface type          | `interface I { +p: number }`   | `interface I { readonly p: number }` |\n| Intersection type       | `type Intersection = T1 \u0026 T2`  | `type Intersection = T1 \u0026 T2`        |\n| Mixed type              | `mixed`                        | `unknown`                            |\n| Null literal type       | `null`                         | `null`                               |\n| Nullable type (Maybe)   | `?number`                      | `number \\| null \\| undefined`        |\n| Number literal type     | `42`                           | `42`                                 |\n| Number type             | `number`                       | `number`                             |\n| Object type             | `{ [string]: number }`         | `{ [key: string]: number }`          |\n| Opaque type             | `opaque type Opaque = number`  | `type Opaque = number`               |\n| String literal type     | `'literal'`                    | `'literal'`                          |\n| String type             | `string`                       | `string`                             |\n| This type               | `this`                         | `this`                               |\n| Tuple type              | `[Date, number]`               | `[Date, number]`                     |\n| Type alias              | `type Type = \u003cFlowType\u003e`       | `type Type = \u003cTSType\u003e`               |\n| Type casting            | `(t: T)`                       | `(t as T)`                           |\n| Type exports / imports  | `import type T from './types'` | `import T from './types`             |\n| Typeof type             | `typeof undefined`             | `undefined`                          |\n| Union type              | `number \\| null`               | `number \\| null`                     |\n| Void type               | `void`                         | `void`                               |\n\n### Utility types\n\n| Utility Type               | Flow                  | TypeScript                |\n| -------------------------- | --------------------- | ------------------------- |\n| Call                       | `$Call\u003cF, T...\u003e`      | `ReturnType\u003cF\u003e`           |\n| Class                      | `Class\u003cT\u003e`            | `typeof T`                |\n| Difference                 | `$Diff\u003cA, B\u003e`         | `Omit\u003cA, keyof B\u003e`        |\n| Element type               | `$ElementType\u003cT, K\u003e`  | `T[k]`                    |\n| Exact                      | `$Exact\u003cT\u003e`           | `T`                       |\n| Existential type           | `*`                   | `any`                     |\n| Keys                       | `$Keys\u003cT\u003e`            | `keyof T`                 |\n| None maybe type            | `$NonMaybeType\u003cT\u003e`    | `NonNullable\u003cT\u003e`          |\n| \u003cs\u003eObject map\u003c/s\u003e          | `$ObjMap\u003cT, F\u003e`       | `any`                     |\n| \u003cs\u003eObject map with key\u003c/s\u003e | `$ObjMapi\u003cT, F\u003e`      | `any`                     |\n| Property type              | `$PropertyType\u003cT, k\u003e` | `T[k]`                    |\n| ReadOnly                   | `$ReadOnly\u003cT\u003e`        | `Readonly\u003cT\u003e`             |\n| Rest                       | `$Rest\u003cA, B\u003e`         | `Omit\u003cA, Union\u003ckeyof B\u003e\u003e` |\n| Shape                      | `$Shape\u003cT\u003e`           | `Partial\u003cT\u003e`              |\n| \u003cs\u003eTuple map\u003c/s\u003e           | `$TupleMap\u003cT, F\u003e`     | `any`                     |\n| Values                     | `$Values\u003cT\u003e`          | `T[keyof T]`              |\n| \u003cs\u003eSubtype\u003c/s\u003e             | _deprecated_          | `any`                     |\n| \u003cs\u003eSupertype\u003c/s\u003e           | _deprecated_          | `any`                     |\n\n\u003csmall\u003e\u003csup\u003e\\*\u003c/sup\u003e\u003c/small\u003e\n\n### Declarations\n\n| Declaration | Flow                                  | TypeScript                                               |\n| ----------- | ------------------------------------- | -------------------------------------------------------- |\n| Class       | `declare class C {}`                  | `declare class C {}`                                     |\n| Export      | `declare export default () =\u003e string` | `const _default: () =\u003e string; export default _default;` |\n| Function    | `declare function f(number): any`     | `declare function f(p: number): any`                     |\n| Interface   | `declare interface I {}`              | `declare interface I {}`                                 |\n| Module      | `declare module 'esmodule' {}`        | `declare module 'esmodule' {}`                           |\n| Type alias  | `declare type T = number`             | `declare type T = number`                                |\n| Variable    | `declare var v: any`                  | `declare var v: any`                                     |\n\nUnsupported: CommonJS export declarations.\n\n---\n\n### Unsupported Flow features / syntax\n\nSome Flow features are not equivalently expressible in TypeScript. The Reflow\nCLI will output a warning with the source code location, whenever one of the\nfollowing cases are encountered:\n\n- **[Constructor return types](https://github.com/Microsoft/TypeScript/issues/11588)**\n\n  TypeScript intentionally doesn't support return types for constructor\n  functions. These will be removed by Reflow.\n\n- **[Existential Type](https://github.com/Microsoft/TypeScript/issues/14466)**\n\n  Flow's\n  [existential type](https://flow.org/en/docs/types/utilities/#toc-existential-type)\n  has been deprecated and should be avoided. Still Reflow supports it and will\n  transform it to `any`.\n\n- **[Function types with unnamed parameters](https://flow.org/en/docs/types/functions/#toc-function-types)**\n\n  In contrast to TypeScript, parameter names can be omitted in Flow. Therefore\n  Reflow inserts parameter names automatically (`p` for a single parameter and\n  `p{i}` for multiple ones).\n\n  ```\n  type FunctionType = ({}, Date) =\u003e string;             // Flow\n  type FunctionType = (p1: {}, p2: Date) =\u003e string;    // TypeScript\n  ```\n\n- **[Index signatures](https://flow.org/en/docs/types/objects/#toc-objects-as-maps)**\n\n  Flow allows any type for keys in index signatures, but Typescript only accepts\n  `string` or `number`. Reflow will add index signatures both for `string` and\n  `number` if a different type is specified in Flow.\n\n  ```\n  // Flow\n  declare type KeyType;\n  interface I = {\n    [key: KeyType]: number\n  }\n\n  // TypeScript\n  interface I = {\n    [key: number]: number;\n    [key: string]: number;\n  }\n  ```\n\n- **[Object type spread](https://flow.org/en/docs/types/objects/#toc-exact-object-types)**\n\n  Object types can be spread into other object types in Flow. Unfortunately this\n  syntax is not supported in TypeScript at the moment. Therefore, these\n  properties will be ommited in output. Please fix affected object types\n  manually.\n\n  ```\n  // Flow\n  type ObjectWithSpread = {\n    prop: mixed;\n    ...ObjectType;\n  };\n\n  // TypeScript\n  type ObjectWithSpread = {\n    prop: unknown;\n  };\n  ```\n\n- **[Opaque Type](https://github.com/Microsoft/TypeScript/issues/14520)**\n\n  Opaque types are not supported in TypeScript and are transformed to an\n  ordinary type alias.\n\n  ```\n  opaque type T = number;  // Flow\n  type T = number;         // TypeScript\n  ```\n\n- **[Variance](https://github.com/Microsoft/TypeScript/issues/1394)**\n\n  Flow's contravariance sigil `-` is not expressible in Typescript and will be\n  omitted. However, TypeScript does support covariance for certain types (`+`\n  becomes `readonly`).\n\n  ```\n  // Flow\n  interface I {\n    +covariant: any;\n    -contravariant: any;\n  }\n\n  // TypeScript\n  interface I {\n    readonly covariant: any;\n    contravariant: any;\n  }\n  ```\n\n- **\\$Call\u003cF, T...\u003e**\n\n  The `$Call\u003cF, T...\u003e` utility type is transformed to TypeScript's\n  `ReturnType\u003cF\u003e`. Since this type only accepts the function type and not the\n  function argument types, it is impossible to infer the return type of\n  polymorphic functions. TypeScript will assume an `unknown` type then.\n\n## Supported syntax\n\nThis Babel plugin enables a few other Babel plugins to support various kinds of\nsyntax:\n\n- [Class properties](https://github.com/tc39/proposal-class-fields)\n- [Decorators](https://github.com/tc39/proposal-decorators)\n- [Dynamic imports](https://github.com/tc39/proposal-dynamic-import)\n- [Nullish coalescence](https://github.com/tc39/proposal-nullish-coalescing)\n- [Optional chaining](https://github.com/tc39/proposal-optional-chaining)\n- [React](https://reactjs.org/)\n- [JSX](https://reactjs.org/docs/introducing-jsx.html)\n\n## Development\n\nClone this repository and install the project dependencies:\n\n```\nyarn install\n```\n\nThere are various npm scripts for different tasks:\n\n```\nyarn build          # Create a production build\nyarn dev            # Build in development mode and watch for changes\nyarn format         # Format the code with Prettier\nyarn lint           # Run ESLint\nyarn test           # Run fixture tests\nyarn test:coverage  # Run the tests with coverage report\nyarn tsc            # Check the types (via TypeScript)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrubersjoe%2Freflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrubersjoe%2Freflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrubersjoe%2Freflow/lists"}