You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* [Dep] upgrade to Recast from 0.20.4 to 0.23.4
**What?**
Upgrade [recast](https://github.com/benjamn/recast) from `0.20.4` to `0.23.4` for more modern parsers. See [changes](benjamn/[email protected]).
As part of the upgrade, the `[email protected]` patch is removed as it is no longer needed.
**Why?**
When the codemod with `[email protected]` removes comments, the parentheses can be incorrectly removed.
Upgrading to `[email protected]` fixes this.
For example, the following Flow type:
```js
const a =
// $FlowFixMe
(1 + 1) * 2;
```
was incorrectly converted to:
```ts
const a = 1 + 1 * 2;
```
With the new version, it gets correctly converted to:
```ts
const a = (1 + 1) * 2;
```
Also, codemod with `[email protected]` keeps the following annotation as is:
```js
type Props = {
it: string,
foo: number
};
````
With [this fix](benjamn/recast#1157) from v0.21.2, the Flow syntax gets correctly converted to the expected TypeScript syntax:
```ts
type Props = {
it: string;
foo: number;
};
```
Lastly, v0.23.4 correctly handles unary expressions by [wrapping unary expressions in parens](benjamn/recast#1361)
* Handle indexed access, `$Partial`, `$ReadOnlySet`, and `$ReadOnlyMap`
**What**
Add the following support (Flow syntax --> TypeScript syntax):
- `T[K]` --> `T[K]`
- `T?.[K]` --> `NonNullable<T>[K] | null | undefined`
- `$Partial<T>` --> `Partial<T>`
- `$ReadOnlySet<T>` --> `ReadonlySet<T>`
- `$ReadOnlyMap<K, V>` --> `ReadonlyMap<K, V>`
**Why**
To support more Flow syntax.
* Fix bugs with maybe function types and interaction types
**Maybe function types**
Flow code
```js
?() => void
```
was incorrectly transformed to:
```ts
() => void | null | undefined
```
It is now correctly transformed to:
```ts
(() => void) | null | undefined
```
**Intersection types**
Flow code
```js
(A | B) & (C | D)
```
was incorrectly transformed to:
```ts
(A | B & C | D)
```
It is now correctly transformed to:
```ts
((A | B) & (C | D))
```
* Fix false positives of privates types
**What**
Fix cases where `A$B` are public types instead of private types:
1. Relay generated types such as `PinRep_pin$data``
2. Type Alias with prefix '$IMPORTED_TYPE$'
**Why**
To avoid false positives in the private types detection
* Add override to force JSX through comment
**What**
If a file contain the comment `@jsx`, treat it as a JSX file.
**Why**
A mock file for a `.tsx` file must have the `.tsx` file extension for jest to find it.
However, if the mock file does not contain any JSX, the codemod would use the file extension `.ts`.
As a workaround, we introduce the ability to add a `@jsx` comment to the mock file to force the codemod to treat it as a JSX file. This ensures the mock file us
es the `.tsx` extension, even if it doesn't contain any JSX.
* Strip flow comments
**What**
- Remove flow-specific ESLint error suppression comments
- Make sure to retain non-flow comments at the top of files
**Why**
The flow-related comments are no longer needed.
Co-authored-by: Jack Hsu <[email protected]>
* [react-router-dom] Improve handling of react-router-dom types
**What**
The following Flow code:
```js
import { type Location, type Match, type RouterHistory } from 'react-router-dom';
type Props = { match: Match };
```
gets correctly converted to TypeScript code:
```ts
import { Location, History as RouterHistory } from 'history';
import { match } from 'react-router-dom';
type Props = {
match: match<{ [key: string]: string | undefined }>
};
```
**Why**
For the following types from `react-router-dom`:
- The `Location` type is moved to `history`.
- The `RouterHistory` type is moved to `history`, and is aliased to `History` instead.
- The `Match` type becomes a generic type `match`.
* [react] improve handling of React types
1. Handle named imports
In addition to supporting `React.*` types:
```js
import * as React from 'react';
type T = React.Node | React.Element | React.ChildrenArray;
```
We also support named imports:
```js
import { type Node as ReactNode, type Element as ReactElement, type ChildrenArray } from 'react';
type T = ReactNode | ReactElement | ChildrenArray;
```
NOTE: To avoid name conflicts with the DOM `Node` and `Element` type, it is important to alias `React.Node` as `ReactNode` and `React.Element` as `ReactElement`.
2. Strip type annotations from React function component return types in favor of inference
Flow:
```js
const App = ({ message }: AppProps): React.Node => <div>{message}</div>;
```
TypeScript:
```ts
const App = ({ message }: AppProps) => <div>{message}</div>;
```
Why not simply change `React.Node` to `React.ReactNode`?
If we leave it as `React.ReactNode`, we'll receive the error `'Component' cannot be used as a JSX component`. To address this, we simply strip out the type annotation from the return type of the function component and allow TypeScript to infer it.
3. Strip out `AbstractComponent` in favor of inference
Flow:
```js
// @flow
const C: React.AbstractComponent<Props, mixed> = React.forwardRef<Props, Ref>(Comp);
export default (forwardRef<Props, Ref>(Comp): React.AbstractComponent<Props, mixed>);
```
TypeScript:
```ts
const C = forwardRef<Ref, Props>(Comp);
export default forwardRef<Ref, Props>(Comp);
```
Why? Because there is no `React.AbstractComponent` equivalent in TypeScript. We can simply strip it out and allow TypeScript to infer the type.
4. Reverse params for `forwardRef`
Flow:
```js
forwardRef<Props, Ref>(Comp);
```
TypeScript:
```ts
forwardRef<Ref, Props>(Comp);
```
Why? Because the arguments are swapped in TypeScript.
5. Rename `ElementConfig`, `ElementProps`, `Portal`, and `StatelessFunctionalComponent`
- `ElementConfig` --> `ComponentProps`
- `ElementProps` --> `ComponentProps`
- `Portal` --> `PortalProps`
- `StatelessFunctionalComponent` --> `FC`
---------
Co-authored-by: Mark Molinaro <[email protected]>
Copy file name to clipboardExpand all lines: NOTES.md
+10-5Lines changed: 10 additions & 5 deletions
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,15 @@
1
1
# Notes
2
-
## React.Node -> React.ReactElement
2
+
## Strip React.Node from function component return types
3
3
4
4
One issue we encountered was most codemods convert `React.Node` to `React.ReactNode` when they're a function return type. While the names are similar, they behave [differently](https://stackoverflow.com/questions/58123398/when-to-use-jsx-element-vs-reactnode-vs-reactelement?rq=1). In TypeScript, `React.ReactNode` is primarily used to type things that can be children of a React node, and it includes things like booleans or null. When we return `React.Node`, we're usually annotating a functional component that can be instantiated in JSX (`<Component />`). In TypeScript that's inferred [as React.ReactElement or JSX.Element](https://github.com/TypeScript-cheatsheets/react#function-components). This also needs to be done for the `render` method of class components as well, despite some of the [React types](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L3087) suggesting otherwise. If you leave it as `React.ReactNode` you'll receive the error `'Component' cannot be used as a JSX component`. In addition, if the function returns `null`, we have to add a `| null` to allow it. Strings and numbers will throw an error if returned in TS.
Object index types work pretty differently between Flow and TypeScript. Flow allows any type to be an index, while TypeScript supports only strings and numbers. One other difference I found is Flow marks all of the keys of the object as optional by default. To get this same behavior, we have to wrap the object in `Partial`.
10
15
@@ -83,7 +88,7 @@ All of the types are imported and namespaced, and the codemod automatically adds
83
88
84
89
## React.AbstractComponent
85
90
86
-
[AbstractComponent](https://flow.org/en/docs/react/types/#toc-react-abstractcomponent) is a Flow type that helps you construct higher order components, and there is no direct TypeScript equivalent. The identical type is a `ComponentType` with the type of `ref` modified. That is a lot more verbose, so we added the `Flow.AbstractComponent` utility to keep things concise.
91
+
[AbstractComponent](https://flow.org/en/docs/react/types/#toc-react-abstractcomponent) is a Flow type that helps you construct higher order components, and there is no direct TypeScript equivalent. We remove the annotations of `AbstractComponent` and allow TypeScript to infer them.
87
92
88
93
## export type * from './foo`
89
94
@@ -94,11 +99,11 @@ In many cases, it's ideal to keep `type` imports when TypeScript supports it. Th
94
99
We've encountered some global Flow types like [`TimeoutID`](https://github.com/facebook/flow/issues/5627) that needed conversions.
Flow has a utility type which gets the props from a component. [TypeScript has a similar type](https://github.com/Microsoft/TypeScript/issues/26704) called `JSX.LibraryManagedAttributes` but there's some extra conversion needed to make the type parameters work.
104
+
Flow has a utility type which gets the props from a component. TypeScript has a similar type called `ComponentProps`.
0 commit comments