Skip to main content

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 FlowRemoved inModern rewrite
$Diff<A, B>0.268.0Typically Omit<A, keyof B> or restructuring. Not always semantically identical — handle case by case.
$Rest<A, B>0.267.0Same status as $Diff. Usually replaceable with Omit + spread.
$PropertyType<T, K>0.266.0T[K] (indexed access).
$ElementType<T, K>0.266.0T[K] (indexed access).
$TupleMap<T, F>0.248.0Mapped 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.0Mapped type with key access and F inlined — e.g. {[K in keyof T]: [K, T[K]]}.
%checks predicate functions0.248.0Type guards — e.g. function isString(x: unknown): boolean %checks becomes function isString(x: unknown): x is string.
$Call<F, ...Args>0.247.0ReturnType<F> plus indexed access, or a conditional type with infer.
$ObjMap<O, F>0.246.0Mapped 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.0Mapped type with key access and F inlined — e.g. {[K in keyof O]: [K, O[K]]}.
React.Element<typeof Foo>0.245.0Prefer 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 FlowModern 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)
mixedunknown

Non-utility syntax forms

Legacy FlowModern Flow
(x: T) castx as T
<T: Bound><T extends Bound>
{| a: number |} exact{a: number} (exact is the default)
+foo / -foo property variance sigilsreadonly foo / writeonly foo keywords (writeonly is Flow-specific)
+T / -T type parameter variance sigilsout T / in T keywords

Discouraged

The form is still recognized by the type checker and does not error, but new code should avoid it.

TypeRecommended 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 / $TupleMap and friends.
  • Type Casting — the as cast syntax that replaces (x: T).
  • Indexed Access Types — the T[K] form that replaces $PropertyType / $ElementType.