website/docs/lang/declaration-merging.md
Flow lets several declarations of the same name combine into one. Two interfaces with the same name union their members; a declare class and an interface fold together; a function or class can carry static members declared in a sibling namespace. Merging primarily shows up in library definitions, though some forms also work in regular source files.
:::info TypeScript comparison
Flow uses the same split-namespace model as TypeScript and supports merging in the cases needed to type declarations. Flow does not support TypeScript's runtime-merging (a namespace contributing runtime members to a sibling function), user-side declare module 'name' { ... } augmentation, or multi-block merging of declare module libdef definitions. See Declaration merging is partially supported for the per-case comparison.
:::
Each name independently inhabits a value namespace and a type namespace, so a single identifier can be both a value and a type without colliding. Value-side uses resolve through the value namespace; type-side uses resolve through the type namespace. Constructs usable in both namespaces (classes, enums) register once on the value side and the type side falls back to it.
const A = 1;
interface A {} // OK — `A` lives in both namespaces independently
const x: number = A; // `A` resolves as a value (the const)
declare const y: A; // `A` resolves as a type (the interface)
interface + interface — members union. Compatible duplicates are allowed; conflicting members error. In library definition files, extends lists also concatenate, call signatures overload as intersections, and a type-parameter arity mismatch errors. In regular source files, the merge is limited to members — extends lists and call signatures don't combine across declarations, and same-named interfaces can't both be exported from a file.declare class + interface — interface members fold into the class (either order).function / declare function + declare namespace — the namespace's type members fold into the function and are accessible as fn.T (either order).class / declare class + declare namespace — the namespace's type members fold into the class and are accessible as Cls.T (either order).declare namespace reliably propagate to its sibling function or class. Value members (e.g., declare const helper: number inside declare namespace fn) are not treated as runtime properties on the host.declare module 'name' { ... } blocks for the same module. A second block is treated as an override of the first, not a union. A libdef for a given module should live in one place.declare module 'name' { ... } from a source file. The form is only valid at the top level of a library file (see Declaring a module in the global namespace for the libdef-only pattern).declare class, declare namespace, and module declarations are most often written.flow files that describe colocated source, another place ambient declarations appearextends mechanics