Modernizing Legacy Flow Syntax
Flow's syntax has evolved substantially over time, with many forms converging on TypeScript-compatible spellings. Many $-prefixed utility types have been renamed, some have been removed entirely, and some legacy syntactic forms have modern keyword equivalents. This page is the canonical reference for what each legacy form should become.
The forms fall into three groups:
- (i) Removed — Flow no longer recognizes these and they must be rewritten.
- (ii) Deprecated — a modern equivalent exists, and the Flow team intends to remove the legacy form in the future. Migrate now — it is cheaper than migrating later.
- (iii) Discouraged — still recognized by the type checker, but new code should avoid the form.
Removed
Flow no longer recognizes these.
| Legacy Flow | Removed in | Modern rewrite |
|---|---|---|
$Diff<A, B> | 0.268.0 | Typically Omit<A, keyof B> or restructuring. Not always semantically identical — handle case by case. |
$Rest<A, B> | 0.267.0 | Same status as $Diff. Usually replaceable with Omit + spread. |
$PropertyType<T, K> | 0.266.0 | T[K] (indexed access). |
$ElementType<T, K> | 0.266.0 | T[K] (indexed access). |
$TupleMap<T, F> | 0.248.0 | Mapped type with the body of F inlined — e.g. $TupleMap<T, <V>(V) => Promise<V>> becomes {[K in keyof T]: Promise<T[K]>}. |
$TupleMapi<T, F> | 0.248.0 | Mapped type with key access and F inlined — e.g. {[K in keyof T]: [K, T[K]]}. |
%checks predicate functions | 0.248.0 | Type guards — e.g. function isString(x: unknown): boolean %checks becomes function isString(x: unknown): x is string. |
$Call<F, ...Args> | 0.247.0 | ReturnType<F> plus indexed access, or a conditional type with infer. |
$ObjMap<O, F> | 0.246.0 | Mapped type with F inlined — e.g. $ObjMap<O, <V>(V) => Promise<V>> becomes {[K in keyof O]: Promise<O[K]>}. |
$ObjMapi<O, F> | 0.246.0 | Mapped type with key access and F inlined — e.g. {[K in keyof O]: [K, O[K]]}. |
React.Element<typeof Foo> | 0.245.0 | Prefer render types when expressing composition constraints ("a Menu only renders MenuItems") — that is what most uses of React.Element<typeof Foo> were really expressing. For generic "any element / any node" positions, use React.MixedElement / React.Node. Reach for ExactReactElement_DEPRECATED<typeof Foo> only as an escape hatch when exact element identity is genuinely required. |
Deprecated
A modern equivalent exists. Some forms already error today; others still parse but are on a deprecation path.
Utility types
| Legacy Flow | Modern Flow |
|---|---|
$Partial<T> | Partial<T> |
$Shape<T> | Partial<T>. Not always semantically identical — $Shape was permissive about depth in ways Partial is not, so migrate per call site rather than blindly renaming. |
$Keys<T> | keyof T |
$ReadOnly<T> | Readonly<T> |
$NonMaybeType<T> | NonNullable<T> |
$ReadOnlyArray<T> | ReadonlyArray<T> |
$ReadOnlyMap<K, V> / $ReadOnlySet<T> / $ReadOnlyWeakMap<K, V> / $ReadOnlyWeakSet<T> | ReadonlyMap / ReadonlySet / ReadonlyWeakMap / ReadonlyWeakSet |
$Values<T> | Values<T> (renamed within Flow's own utilities) |
mixed | unknown |
Non-utility syntax forms
| Legacy Flow | Modern Flow |
|---|---|
(x: T) cast | x as T |
<T: Bound> | <T extends Bound> |
{| a: number |} exact | {a: number} (exact is the default) |
+foo / -foo property variance sigils | readonly foo / writeonly foo keywords (writeonly is Flow-specific) |
+T / -T type parameter variance sigils | out T / in T keywords |
Discouraged
The form is still recognized by the type checker and does not error, but new code should avoid it.
| Type | Recommended approach |
|---|---|
$Exact<T> | Define the exact type first and derive inexact variants from it via object type spread ({...Exact, ...}). See $Exact<T> (Discouraged). |
$-prefixed utilities that are not deprecated
A few $-prefixed types remain first-class Flow utilities — the $ is just part of the name, not a marker of being deprecated. They are esoteric and rarely encountered, but if you do hit one, keep using it. Examples include $KeyMirror<O> and $Exports<...>. See Utility Types for the current list.
See also
- Flow for TypeScript Users — broader comparison of Flow and TypeScript, including the TS-aligned subset of the renames covered here.
- Utility Types — reference for Flow's current utility types.
- Mapped Types — the modern replacement for
$ObjMap/$TupleMapand friends. - Type Casting — the
ascast syntax that replaces(x: T). - Indexed Access Types — the
T[K]form that replaces$PropertyType/$ElementType.