From 7ee6944e5f96758da9e33caecefc6b0bddcea600 Mon Sep 17 00:00:00 2001 From: Sherry Date: Thu, 29 Oct 2026 08:21:08 -0700 Subject: [PATCH] [lexical] Bug Fix: Keep the deprecated unchecked node type arguments in the Flow declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description v0.53.0 (#9479) removed the unchecked type-argument overloads of `getParent`, `getParentOrThrow`, `getParents`, `getPreviousSibling`, `getPreviousSiblings`, `getNextSibling`, `getNextSiblings`, `getChildren`, `getFirstChild`, `getFirstChildOrThrow`, `getLastChild`, `getLastChildOrThrow`, `getChildAtIndex`, `getFirstDescendant`, `getLastDescendant`, `getDescendantByIndex`, `$getNodeByKey` and `$getNodeByKeyOrThrow` from the TypeScript declarations and, in the same release, from the hand-maintained Flow declarations in `packages/lexical/flow/Lexical.js.flow`. TypeScript carried those overloads as `@deprecated` for several releases before removing them, so a TypeScript codebase was told in its editor long before the call sites stopped checking. Flow has no deprecation signal: the `@deprecated` tag on a `.js.flow` declaration is a comment and nothing reads it, so for Flow this was a removal with no notice at all. Every call site that passes a type argument fails at once with `nonpolymorphic-type-arg`, and the `prop-missing` and `incompatible-type` errors that follow where the cast was load-bearing. The upgrade has no codemod, by design — each site needs the guard that fits its context — so a large Flow codebase cannot cross this in one step. Restore the overloads in the Flow declarations only, still `@deprecated`, with the comment saying that the TypeScript overload is gone and that these stay until the remaining Flow call sites are migrated. TypeScript is unchanged, the guidance in `traversals.md` is unchanged, and new code in either language should call these methods without a type argument and narrow the result with a node guard. ## Test plan ### Before `flow check` over Meta's www Flow root with v0.53.0's declarations in place (paths redacted): ``` Error --------------------------------------------------------------------- /SomeLayoutPlugin.js:129:26 Cannot call non-polymorphic `() => Array` [1] with type arguments. [nonpolymorphic-type-arg] 129| const children = node.getChildren(); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ References: html/shared/lexical/Lexical.js.flow:974:3 974| getChildren(): LexicalNode[]; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [1] Found 2174 errors ``` ### After The same root, same revision, with this change applied to `Lexical.js.flow`: ``` $ flow check . No errors! real 10m6.650s ``` The OSS checks were not run in this environment (its package manager is not available there); CI runs `pnpm run ci-check` on this PR. --- ...tore-flow-unchecked-node-type-arguments.md | 28 ++++ packages/lexical/flow/Lexical.js.flow | 152 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 .changeset/restore-flow-unchecked-node-type-arguments.md diff --git a/.changeset/restore-flow-unchecked-node-type-arguments.md b/.changeset/restore-flow-unchecked-node-type-arguments.md new file mode 100644 index 00000000000..ddb78f9a483 --- /dev/null +++ b/.changeset/restore-flow-unchecked-node-type-arguments.md @@ -0,0 +1,28 @@ +--- +'lexical': patch +--- + +[fix] Keep the deprecated unchecked node type arguments in the Flow declarations + +v0.53.0 removed the unchecked type-argument overloads of `getParent`, +`getParentOrThrow`, `getParents`, `getPreviousSibling`, `getPreviousSiblings`, +`getNextSibling`, `getNextSiblings`, `getChildren`, `getFirstChild`, +`getFirstChildOrThrow`, `getLastChild`, `getLastChildOrThrow`, +`getChildAtIndex`, `getFirstDescendant`, `getLastDescendant`, +`getDescendantByIndex`, `$getNodeByKey` and `$getNodeByKeyOrThrow` from the +TypeScript declarations and from the hand-maintained Flow declarations in the +same release. TypeScript had shown them as `@deprecated` for several releases +before that; Flow has no deprecation signal, so a Flow codebase saw no warning +at all and every call site that passes a type argument stopped checking at +once, with `nonpolymorphic-type-arg` and the `prop-missing` errors that follow +it. + +The overloads are back in the Flow declarations only, still `@deprecated` and +still unchecked casts. TypeScript is unchanged: it has no such overloads, and +new code in either language should call these methods without a type argument +and narrow the result with a node guard, as +[Narrowing traversal results](https://lexical.dev/docs/concepts/traversals#narrowing-traversal-results) +describes. + +Removal: not scheduled; it needs the remaining Flow call sites to be migrated +first. diff --git a/packages/lexical/flow/Lexical.js.flow b/packages/lexical/flow/Lexical.js.flow index f9519bbace9..797b63b18d7 100644 --- a/packages/lexical/flow/Lexical.js.flow +++ b/packages/lexical/flow/Lexical.js.flow @@ -546,15 +546,71 @@ declare export class LexicalNode { getKey(): NodeKey; getIndexWithinParent(): number; getParent(): ElementNode | null; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getParent(): T | null; getParentOrThrow(): ElementNode; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getParentOrThrow(): T; getTopLevelElement(): DecoratorNode | ElementNode | null; getTopLevelElementOrThrow(): DecoratorNode | ElementNode; getParents(): ElementNode[]; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getParents(): T[]; getParentKeys(): NodeKey[]; getPreviousSibling(): LexicalNode | null; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getPreviousSibling(): T | null; getPreviousSiblings(): LexicalNode[]; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getPreviousSiblings(): T[]; getNextSibling(): LexicalNode | null; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getNextSibling(): T | null; getNextSiblings(): LexicalNode[]; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getNextSiblings(): T[]; is(object: ?LexicalNode): boolean; isBefore(targetNode: LexicalNode): boolean; isParentOf(targetNode: LexicalNode): boolean; @@ -950,19 +1006,99 @@ declare export class ElementNode extends LexicalNode { getFormatType(): ElementFormatType; getIndent(): number; getChildren(): LexicalNode[]; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getChildren(): T[]; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getChildren(): T; getChildrenKeys(): NodeKey[]; getChildrenSize(): number; isEmpty(): boolean; isDirty(): boolean; getAllTextNodes(): TextNode[]; getFirstDescendant(): null | LexicalNode; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getFirstDescendant(): null | T; getLastDescendant(): null | LexicalNode; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getLastDescendant(): null | T; getDescendantByIndex(index: number): null | LexicalNode; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getDescendantByIndex(index: number): null | T; getFirstChild(): null | LexicalNode; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getFirstChild(): null | T; getFirstChildOrThrow(): LexicalNode; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getFirstChildOrThrow(): T; getLastChild(): null | LexicalNode; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getLastChild(): null | T; getLastChildOrThrow(): LexicalNode; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getLastChildOrThrow(): T; getChildAtIndex(index: number): null | LexicalNode; + /** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this method without a type argument and narrow the result with a type + * guard instead. + */ + getChildAtIndex(index: number): null | T; getTextContent(): string; getDirection(): 'ltr' | 'rtl' | null; hasFormat(type: ElementFormatType): boolean; @@ -1129,7 +1265,23 @@ declare export function $getNodeByKey( key: NodeKey, _editorState?: EditorState, ): LexicalNode | null; +/** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this function without a type argument and narrow the result with a type + * guard instead. + */ +declare export function $getNodeByKey(key: NodeKey): N | null; declare export function $getNodeByKeyOrThrow(key: NodeKey): LexicalNode; +/** + * @deprecated The type parameter is an unchecked and unsafe cast. The + * TypeScript overload was removed in v0.53.0; this Flow overload is kept + * until the Flow call sites that pass a type argument are migrated. Call + * this function without a type argument and narrow the result with a type + * guard instead. + */ +declare export function $getNodeByKeyOrThrow(key: NodeKey): N; declare export function $getRoot(): RootNode; declare export function $isLeafNode( node: ?LexicalNode,