Package Exports
- babel-plugin-reflow
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (babel-plugin-reflow) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Reflow
Babel plugin to transpile a Flow typed codebase to TypeScript.
This is still in an early stage and may break anytime!
Reflow enables you to migrate a whole Flow based project to TypeScript by transpiling the Flow type annotations to equivalent TypeScript code. While this reduces the effort to move a large code base to TypeScript drastically, it is still likely that you will need to manually fix new type errors afterwards. This program helps you with the tedious task to convert Flow syntax to TypeScript, but it can not magically fix type errors which occur after the migration.
See this repository for an excellent overview of the differences and similarities of Flow and Typescript.
Installation
yarn add --dev babel-plugin-reflowUsage
CLI
This package includes a small CLI wrapper for the Babel plugin to recursively transpile a whole
project directory. 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 babel-plugin-reflowUsage is as follows:
$ npx reflow --help
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 instead of creating new TS files next to the original JS files.
-D, --replace-decorators Replace class @decorators with wrapped function calls to avoid TypeScript errors
-h, --help output usage information
Examples:
$ reflow --replace src/
$ reflow -d -i '**/__tests__/**/*.{js,jsx} src/
$ reflow -exclude-patterns '**/__tests__/**/*','fixtures/*.js' src/Programmatically
TODO
As Babel plugin (not recommended)
TODO
Transformations
Base types
The following examples have been chosen to show some of the syntax differences between Flow and TypeScript. Most syntax is similiar, but there are differences and also certain edge cases, which need to be handled while transpiling the types. A few types are not equivalently expressible in TypeScript and will result in a small loss of type information. See the list of unsupported Flow features in TypeScript below.
| Type | Flow | TypeScript |
|---|---|---|
| Any type | any |
any |
| 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, {}) => number |
(p1: string, p2: {}) => number |
| Generic type annotation | let v: <FlowType> |
let v: <TSType> |
| Generics | type Generic<T: Super> = T |
type Generic<T extends Super> = T |
| Interface type | interface { +p: number } |
interface { readonly p: number } |
| 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 |
| 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) |
| Type exports / imports | import type T from './types' |
import T from './types |
| Typeof type | typeof undefined |
undefined |
| Union type | number | null |
number | null |
| Void type | void |
void |
Utility types
| Utility Type | Flow | TypeScript |
|---|---|---|
| Call | $Call<F, T...> |
ReturnType<F> |
| Class | Class<T> |
typeof T |
| Difference | $Diff<A, B> |
Omit<A, keyof B> |
| Element type | $ElementType<T, K> |
T[k] |
| Exact | $Exact<T> |
T |
| Existential type | * |
any |
| Keys | $Keys<T> |
keyof T |
| None maybe type | $NonMaybeType<T> |
NonNullable<T> |
| Object map | $ObjMap<T, F> |
– |
| Object map with key | $ObjMapi<T, F> |
– |
| Property type | $PropertyType<T, k> |
T[k] |
| ReadOnly | $ReadOnly<T> |
Readonly<T> |
| Rest | $Rest<A, B> |
– |
| Shape | $Shape<T> |
Partial<T> |
| Tuple map | $TupleMap<T, F> |
– |
| Values | $Values<T> |
T[keyof T] |
| deprecated | – | |
| deprecated | – |
*
Declarations
| Declaration | Flow | TypeScript |
|---|---|---|
| Declare ES module export | declare export default () => string |
const _default: () => string; export default _default; |
| 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 v: string |
var v: string |
| Declare type alias | declare type T: number |
declare type T = number |
| Declare variable | declare var v: any |
declare var v: any |
Unsupported: CommonJS export declarations.
Unsupported Flow features / syntax
The following Flow features are not equivalently expressible in TypeScript and need to be handled differently:
-
TypeScript intentionally doesn't support return types for constructor functions. These will be removed by Reflow.
-
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 (
pfor a single parameter andp{i}for multiple ones).type FunctionType = ({}, Date) => string; // Flow type FunctionType = (p1: {}, p2: Date) => string; // TypeScript-
Flow allows any type for keys in index signatures, but Typescript only accepts
stringornumber. Reflow will add index signatures both forstringandnumberif 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 types are not supported in TypeScript and are transformed to an ordinary type alias.
opaque type T = number; // Flow type T = number; // TypeScript -
Flow's contravariance sigil
-is not expressible in Typescript and will be omitted. However, TypeScript does support covariance for certain types (+becomesreadonly).// Flow interface I { +covariant: any; -contravariant: any; } // TypeScript interface I { readonly covariant: any; contravariant: any; } $Call<F, T...>
The
$Call<F, T...>utility type is transformed to TypeScript'sReturnType<F>. Since this type only accepts the function type and not the function argument types, it is impossible to infer the return type of polymorphic functions. TypeScript will assume anunknowntype then.
Supported syntax
This Babel plugin has built-in support for
- React
- JSX
- Class properties (proposal)
- Dynamic imports (proposal)
- Decorators (proposal)
Development
Clone this repository and install the project dependencies:
yarn installThere are various npm scripts for different tasks:
yarn build # Create a production build
yarn dev # Build in development mode and watch for changes
yarn format # Format the code with Prettier
yarn lint # Run ESLint
yarn test # Run fixture tests
yarn test:coverage # Run the tests with coverage report
yarn tsc # Check the types (via TypeScript)