Skip to content
Babel plugin to migrate a Flow JS code to TypeScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci
.vscode
src
.eslintignore
.eslintrc.json
.flowconfig
.gitignore
.gitlab-ci.yml
.prettierignore
.prettierrc.json
README.md
babel.config.js
jest.config.js
package.json
tsconfig.json
webpack.config.js
yarn.lock

README.md

Reflow

Babel Plugin to migrate a Flow JS typed JavaScript code base to TypeScript.

CircleCI Coverage

Careful! This is still in an early stage and may break anytime.

Reflow transforms your Flow JS type annotations to equivalent TypeScript code. While this should reduce the effort to migrate a large code base to TypeScript drastically, you will most likely still need to manually fix and refactor the resulting code. After the transformation new type errors will probably occur and existing type annotations may prove to be inaccurate. This program helps you with the tedious task to migrate Flow syntax to TypeScript, but it can't magically fix semanticproblems obviously.

The type system of TypeScript and Flow share a lot of similarities but still there are some fundamental and many subtle differences. See this excellent repository for a detailed comparison and good overview. One major difference for example is the purely structural type system of TypeScript versus the partly nominal one used in Flow JS.

Reflow has built-in support for React, JSX and some proposed JavaScript features like class properties, dynamic imports and decorators.

Installation

yarn add --dev TBA

Usage

CLI

Install the package as project dependency and run npx reflow afterwards. Alternatively you might want to install Reflow globally so you can simply type reflow:

yarn global add TBA

Usage is as follows:

Usage: reflow [OPTION]... <FILES OR DIRECTORIES ...>

Reflow

Options:
  -V, --version                    output the version number
  -d, --dry-run                    perform a trial run printing to stdout instead of writing a file
  -e, --exclude-dirs <dirs ...>    list of recursively excluded directories (default: ["node_modules"])
  -i, --include-pattern <pattern>  set the glob pattern for input files (default: "**/*.{js,jsx}")
  -r, --replace                    process files in-place. A new TS file will be created next to the original file otherwise.
  -v, --verbose                    increase verbosity
  -h, --help                       output usage information

Examples:
  $ reflow --write src/
  $ reflow -exclude-patterns '**/__tests__/**/*','mocks/*.js' src/lib/

Programmatically

TODO

As Babel plugin (not recommended)

This is probably a bad idea. Please don't do that.

Transformations

Base types

The following examples have been chosen to show some of the syntax differences between Flow and TypeScript. Bold types need to be transformed, the ones with a warning sign can't be expressed completely equivalently in TypeScript and will result in a loss of (some) type information. See the list of unsupported Flow features in TypeScript below. Some type annotations don't require any transformation, since they share the same syntax in Flow and TypeScript.

Done Type Flow TypeScript
Array type Array<number> Array<number>
Boolean literal type true true
Boolean type boolean boolean
Empty type empty never
Exact object type {| p: number |} { p: number }
Function type (string, boolean) => number (p1: string, p2: boolean) => number
Generic type annotation let v: <FlowType> let v: <TSType>
Generics type Generic<T: SuperClass> = T type Generic<T extends SuperClass> = T
Interface type ⚠️ interface { +p1: number, p2: null } interface { readonly p1: number, p2: null }
Intersection type type Intersection = T1 & T2 type Intersection = T1 & T2
Mixed type mixed unknown
Null literal type null null
Nullable type = Maybe ?number number | null | undefined
Number literal type 42 42
Number type number number
Module exports / imports import type T from './types' import T from './types
Object type { [string]: number } { [key: string]: number }
Opaque type ⚠️ opaque type Opaque = number type Opaque = number
String literal type 'literal' 'literal'
String type string string
This type this this
Tuple type [Date, number] [Date, number]
Type alias type Type = <FlowType> type Type = <TSType>
Type casting (t: T) (t as T)
Typeof type typeof undefined undefined
Union type number | null number | null
Void type void void

Utility types

Done Utility Type Flow TypeScript
🚧 Call $Call<F, T...> TODO
Class Class<T> typeof T
🚧 Difference $Diff<A, B> TODO
🚧 Element type $ElementType<T, K> T[k]
🚧 Exact $Exact<T> T
Existential type ⚠️ * any
🚧 Keys $Keys<T> keyof T
🚧 None maybe type $NonMaybeType<T> TODO
🚧 Object map $ObjMap<T, F> TODO
🚧 Object map with key $ObjMapi<T, F> TODO
🚧 Property type $PropertyType<T, k> T[k]
🚧 Tuple map $TupleMap<T, F> TODO
ReadOnly $ReadOnly<T> Readonly<T>
🚧 Rest $Rest<A, B> Exclude
🚧 Return type $Call<F> ReturnType
🚧 Shape $Shape<T> TODO
🚧 Values $Values<T> T[keyof T]
Subtype deprecated
Supertype deprecated

Declarations

Done Declaration Flow TypeScript
Declare class declare class C {} declare class C {}
Declare function declare function f(number): any declare function f(p: number): any
Declare interface declare interface I {} declare interface I {}
Declare module declare module 'esmodule' {} declare module 'esmodule' {}
Declare module statement declare var varInModuleDeclaration: string var varInModuleDeclaration: string
Declare ES module export declare export default () => string const _default: () => string; export default _default;
🚧 Declare CommonJS module export TODO TODO
Declare type alias declare type T: number declare type T = number
Declare variable declare var v: any declare var v: any

Unsupported FlowJS features / syntax

The following Flow features are not equivalently expressible or need to be adapted in TypeScript:

  • Constructor return types

    TypeScript intentionally doesn't support return types for constructor functions. These will be removed by Reflow.

  • Existential Type

    Flow's existential type has been deprecated and should be avoided. Still Reflow supports it and will transform it to any.

  • Function types with unnamed parameters

    In contrast to TypeScript, parameter names can be omitted in Flow. Therefore Reflow inserts parameter names automatically (p for a single parameter and p{i} for multiple ones).

    type FunctionType = ({}, Date) => string;             // Flow
    type FunctionType = (p1: {}, p2: Date) => string;    // TypeScript
    
  • Index signatures

    Flow allows any type for keys in index signatures, but Typescript only accepts string or number. Reflow will add index signatures both for string and number if a different type is specified in Flow.

    // Flow
    declare type KeyType;
    interface I = {
      [key: KeyType]: number
    }
    
    // TypeScript
    interface I = {
      [key: number]: number;
      [key: string]: number;
    }
    
  • Opaque Type

    Opaque types are not supported in TypeScript and are transformed to an ordinary type alias.

    opaque type T = number;  // Flow
    type T = number;         // TypeScript
    
  • Variance

    Flow's contravariance sigil - is not expressible in Typescript and will be omitted. However, TypeScript does support covariance for certain types (+ becomes readonly).

    // Flow
    interface I {
      +covariant: any;
      -contravariant: any;
    }
    
    // TypeScript
    interface I {
      readonly covariant: any;
      contravariant: any;
    }
    

Development

Clone this repository and install the project dependencies:

yarn install

There are various npm scripts for different tasks:

yarn build          # Create a production build
yarn format         # Format the code with Prettier
yarn dev            # Build in development mode and watch for changes
yarn lint           # Run ESLint
yarn test           # Run fixture tests
yarn test:coverage  # Run the tests with coverage report
yarn typecheck      # Check the types (via TypeScript)
You can’t perform that action at this time.