diff --git a/src/typing/errors/error_message.ml b/src/typing/errors/error_message.ml
index cf40a19beec..89c29c49f4e 100644
--- a/src/typing/errors/error_message.ml
+++ b/src/typing/errors/error_message.ml
@@ -788,6 +788,7 @@ let map_loc_of_explanation (f : 'a -> 'b) =
{ name; declaration = f declaration; providers = Base.List.map ~f providers }
| ExplanationConcreteEnumCasting { representation_type; casting_syntax } ->
ExplanationConcreteEnumCasting { representation_type; casting_syntax }
+ | ExplanationFunctionsWithStaticsToObject -> ExplanationFunctionsWithStaticsToObject
| ExplanationMultiplatform -> ExplanationMultiplatform
| ExplanationNonCallableObjectToFunction -> ExplanationNonCallableObjectToFunction
| ExplanationPropertyInvariantTyping -> ExplanationPropertyInvariantTyping
diff --git a/src/typing/errors/flow_intermediate_error.ml b/src/typing/errors/flow_intermediate_error.ml
index 4e239727e9f..d96175c2e03 100644
--- a/src/typing/errors/flow_intermediate_error.ml
+++ b/src/typing/errors/flow_intermediate_error.ml
@@ -1091,6 +1091,8 @@ let to_printable_error :
text
"https://flow.org/en/docs/faq/#why-cant-i-pass-an-arraystring-to-a-function-that-takes-an-arraystring-number";
]
+ | ExplanationFunctionsWithStaticsToObject ->
+ [text "Functions without statics are not compatible with objects"]
| ExplanationMultiplatform ->
[
text "Read the docs on Flow's multi-platform support for more information: ";
diff --git a/src/typing/errors/flow_intermediate_error_types.ml b/src/typing/errors/flow_intermediate_error_types.ml
index 2dc13907ec8..bddd8bb76e2 100644
--- a/src/typing/errors/flow_intermediate_error_types.ml
+++ b/src/typing/errors/flow_intermediate_error_types.ml
@@ -179,6 +179,7 @@ type 'loc explanation =
representation_type: string;
casting_syntax: Options.CastingSyntax.t;
}
+ | ExplanationFunctionsWithStaticsToObject
| ExplanationMultiplatform
| ExplanationNonCallableObjectToFunction
| ExplanationPropertyInvariantTyping
diff --git a/src/typing/flow_js_utils.ml b/src/typing/flow_js_utils.ml
index 8c3e6518b1e..f28999cdeb9 100644
--- a/src/typing/flow_js_utils.ml
+++ b/src/typing/flow_js_utils.ml
@@ -807,19 +807,35 @@ let quick_error_fun_as_obj cx ~use_op reason statics reason_o props =
not (optional || is_function_prototype x || NameUtils.Map.mem x statics_own_props))
props
in
- NameUtils.Map.iter
- (fun x _ ->
- let use_op =
- Frame (PropertyCompatibility { prop = Some x; lower = reason; upper = reason_o }, use_op)
- in
- let reason_prop = update_desc_reason (fun desc -> RPropertyOf (x, desc)) reason_o in
- let err =
- Error_message.EPropNotFound
- { prop_name = Some x; reason_prop; reason_obj = reason; use_op; suggestion = None }
- in
- add_output cx err)
- props_not_found;
- not (NameUtils.Map.is_empty props_not_found)
+ if NameUtils.Map.is_empty props_not_found then
+ false
+ else if NameUtils.Map.is_empty statics_own_props && not (NameUtils.Map.is_empty props) then (
+ let error_message =
+ Error_message.EIncompatibleWithUseOp
+ {
+ reason_lower = reason;
+ reason_upper = reason_o;
+ use_op;
+ explanation = Some Flow_intermediate_error_types.ExplanationFunctionsWithStaticsToObject;
+ }
+ in
+ add_output cx error_message;
+ true
+ ) else (
+ NameUtils.Map.iter
+ (fun x _ ->
+ let use_op =
+ Frame (PropertyCompatibility { prop = Some x; lower = reason; upper = reason_o }, use_op)
+ in
+ let reason_prop = update_desc_reason (fun desc -> RPropertyOf (x, desc)) reason_o in
+ let err =
+ Error_message.EPropNotFound
+ { prop_name = Some x; reason_prop; reason_obj = reason; use_op; suggestion = None }
+ in
+ add_output cx err)
+ props_not_found;
+ true
+ )
| None -> false
(** Instantiation *)
diff --git a/tests/call_properties/call_properties.exp b/tests/call_properties/call_properties.exp
index 310785bdb31..b1cf2e2f99a 100644
--- a/tests/call_properties/call_properties.exp
+++ b/tests/call_properties/call_properties.exp
@@ -227,8 +227,8 @@ References:
Error -------------------------------------------------------------------------------------------------------- E.js:2:32
-Cannot assign function to `a` because property `someProp` is missing in function [1] but exists in object type [2].
-[prop-missing]
+Cannot assign function to `a` because function [1] is incompatible with object type [2]. Functions without statics are
+not compatible with objects. [incompatible-type]
E.js:2:32
2| var a : { someProp: number } = function () {};
diff --git a/tests/component_syntax/component_syntax.exp b/tests/component_syntax/component_syntax.exp
index c751a89d906..a1eb50a98fd 100644
--- a/tests/component_syntax/component_syntax.exp
+++ b/tests/component_syntax/component_syntax.exp
@@ -2729,7 +2729,7 @@ Error --------------------------------------------------------------------------
Cannot create `meta` element because in property `ref`: [incompatible-type]
- Either `HTMLAnchorElement` [1] is incompatible with `HTMLMetaElement` [2] in the first parameter.
- - Or property `current` is missing in function type [3] but exists in object type [4].
+ - Or function type [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
propsof.js:28:22
28| let b = ; // error
@@ -2844,7 +2844,7 @@ Error --------------------------------------------------------------------------
Cannot declare ref because: [incompatible-type]
- Either component Reffed [1] is incompatible with null [2] in the first parameter.
- - Or property `current` is missing in function type [3] but exists in object type [4].
+ - Or function type [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
The `ref` parameter must be a subtype of `React.RefSetter`.
@@ -3142,7 +3142,8 @@ References:
Error ----------------------------------------------------------------------------------------------------- refs.js:17:2
Cannot cast `Baz` to component because: [incompatible-cast]
- - Either property `current` is missing in function type [1] but exists in object type [2].
+ - Either function type [1] is incompatible with object type [2]. Functions without statics are not compatible with
+ objects.
- Or component Reffed [3] is incompatible with string [4] in the first parameter.
refs.js:17:2
@@ -3195,7 +3196,7 @@ Error --------------------------------------------------------------------------
Cannot create `MyNestedInput` element because in property `ref`: [incompatible-type]
- Either `HTMLElement` [1] is incompatible with nullable `HTMLInputElement` [2] in the first parameter.
- Or `HTMLElement` [1] is incompatible with `HTMLInputElement` [3] in the first parameter.
- - Or property `current` is missing in function type [4] but exists in object type [5].
+ - Or function type [4] is incompatible with object type [5]. Functions without statics are not compatible with objects.
refs.js:64:53
64|
@@ -3252,7 +3253,7 @@ Error --------------------------------------------------------------------------
Cannot create `Foo` element because in property `ref`: [incompatible-type]
- Either number [1] is incompatible with boolean [2] in property `bar` of the first parameter.
- - Or property `current` is missing in function type [3] but exists in object type [4].
+ - Or function type [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
refs.js:92:13
92| ; // error
@@ -3321,7 +3322,7 @@ References:
Error --------------------------------------------------------------------------------------------------- refs.js:108:23
Cannot create `GenericRef2` element because in property `ref`: [incompatible-type]
- - Either property `current` is missing in function [1] but exists in object type [2].
+ - Either function [1] is incompatible with object type [2]. Functions without statics are not compatible with objects.
- Or array type [3] is incompatible with string [4] in the first parameter.
refs.js:108:23
diff --git a/tests/component_type/component_type.exp b/tests/component_type/component_type.exp
index 559a260d847..840d8e9534e 100644
--- a/tests/component_type/component_type.exp
+++ b/tests/component_type/component_type.exp
@@ -35,7 +35,8 @@ References:
Error ----------------------------------------------------------------------------------- class_to_component_type.js:7:1
Cannot cast `Foo` to component because: [incompatible-cast]
- - Either property `current` is missing in function type [1] but exists in object type [2].
+ - Either function type [1] is incompatible with object type [2]. Functions without statics are not compatible with
+ objects.
- Or `Foo` [3] is incompatible with string [4] in the first parameter.
class_to_component_type.js:7:1
@@ -191,7 +192,7 @@ Error --------------------------------------------------------------------------
Cannot cast `ComponentNarrower` to component because: [incompatible-cast]
- Either `ComponentNarrower` [1] is incompatible with `Component` [2] in the first parameter.
- - Or property `current` is missing in function type [3] but exists in object type [4].
+ - Or function type [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
classes_lower.js:19:1
19| ComponentNarrower as component(ref: React.RefSetter, ...any); // Error instance type is wrong
@@ -241,7 +242,7 @@ Error --------------------------------------------------------------------------
Cannot cast `Component` to component because: [incompatible-cast]
- Either `Component` [1] is incompatible with `Subclass` [2] in the first parameter.
- - Or property `current` is missing in function type [3] but exists in object type [4].
+ - Or function type [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
classes_lower.js:25:1
25| Component as component(ref: React.RefSetter, ...any); // Ok, Instance is covariant
@@ -618,7 +619,7 @@ Error --------------------------------------------------------------------------
Cannot cast `Component` to component because: [incompatible-cast]
- Either undefined [1] is incompatible with null [2] in the first parameter.
- - Or property `current` is missing in function type [1] but exists in object type [3].
+ - Or function type [1] is incompatible with object type [3]. Functions without statics are not compatible with objects.
function_lower.js:12:1
12| Component as component(ref: React.RefSetter, ...Props); // Error
@@ -748,7 +749,7 @@ Error --------------------------------------------------------------------------
Cannot cast `Foo` to component because: [incompatible-cast]
- Either undefined [1] is incompatible with null [2] in the first parameter.
- - Or property `current` is missing in function type [1] but exists in object type [3].
+ - Or function type [1] is incompatible with object type [3]. Functions without statics are not compatible with objects.
function_to_component_type.js:8:1
8| Foo as component( // error: void ~> string
diff --git a/tests/function_statics/function_statics.exp b/tests/function_statics/function_statics.exp
index eb9be9f7c78..02d1aaf99e1 100644
--- a/tests/function_statics/function_statics.exp
+++ b/tests/function_statics/function_statics.exp
@@ -65,8 +65,8 @@ References:
Error --------------------------------------------------------------------------------------------------- arrow.js:33:43
-Cannot assign function to `f` because property `a` is missing in function [1] but exists in object type [2].
-[prop-missing]
+Cannot assign function to `f` because function [1] is incompatible with object type [2]. Functions without statics are
+not compatible with objects. [incompatible-type]
arrow.js:33:43
33| const f: {(): number, a: string, ...} = () => 1; // ERROR on assignment
@@ -255,8 +255,8 @@ References:
Error ------------------------------------------------------------------------------------- function_expression.js:41:43
-Cannot assign function to `f` because property `a` is missing in function [1] but exists in object type [2].
-[prop-missing]
+Cannot assign function to `f` because function [1] is incompatible with object type [2]. Functions without statics are
+not compatible with objects. [incompatible-type]
function_expression.js:41:43
41| const f: {(): number, a: string, ...} = function () { return 1}; // ERROR on assignment
@@ -298,8 +298,8 @@ References:
Error ---------------------------------------------------------------------------------- used_as_callable_object.js:33:2
-Cannot cast `add` to `InexactCallableObj` because property `bar` is missing in function [1] but exists in
-`InexactCallableObj` [2]. [prop-missing]
+Cannot cast `add` to `InexactCallableObj` because function [1] is incompatible with `InexactCallableObj` [2]. Functions
+without statics are not compatible with objects. [incompatible-cast]
used_as_callable_object.js:33:2
33| (add: InexactCallableObj); // error prop 'bar' missing
diff --git a/tests/new_react/new_react.exp b/tests/new_react/new_react.exp
index d19dd879d7c..8764e03c9a0 100644
--- a/tests/new_react/new_react.exp
+++ b/tests/new_react/new_react.exp
@@ -42,8 +42,8 @@ References:
Error -------------------------------------------------------------------------------------------------- classes.js:23:3
-Cannot extend `React.Component` [1] with `Foo` because property `y_` is missing in function type [2] but exists in
-object type [3] in the first parameter of property `setState`. [prop-missing]
+Cannot extend `React.Component` [1] with `Foo` because property `y_` is missing in object type [2] but exists in object
+type [3] in the first parameter of property `setState`. [prop-missing]
classes.js:23:3
23| setState(o: { y_: string }): void { }
@@ -53,39 +53,36 @@ References:
classes.js:7:19
7| class Foo extends React.Component {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [1]
- /react.js:39:49
- 39| partialState: ?$ReadOnly> | ((State, Props) => ?$ReadOnly>),
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [2]
+ classes.js:7:42
+ 7| class Foo extends React.Component {
+ ^^^^^ [2]
classes.js:23:15
23| setState(o: { y_: string }): void { }
^^^^^^^^^^^^^^ [3]
-Error -------------------------------------------------------------------------------------------------- classes.js:23:3
+Error ------------------------------------------------------------------------------------------------- classes.js:23:15
-Cannot extend `React.Component` [1] with `Foo` because property `y_` is missing in object type [2] but exists in object
-type [3] in the first parameter of property `setState`. [prop-missing]
+Cannot extend `React.Component` [1] with `Foo` because object type [2] is incompatible with nullable `$ReadOnly` [3] in
+the first parameter of property `setState`. [incompatible-extend]
- classes.js:23:3
+ classes.js:23:15
23| setState(o: { y_: string }): void { }
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ ^^^^^^^^^^^^^^ [2]
References:
classes.js:7:19
7| class Foo extends React.Component {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [1]
- classes.js:7:42
- 7| class Foo extends React.Component {
- ^^^^^ [2]
- classes.js:23:15
- 23| setState(o: { y_: string }): void { }
- ^^^^^^^^^^^^^^ [3]
+ /react.js:39:19
+ 39| partialState: ?$ReadOnly> | ((State, Props) => ?$ReadOnly>),
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^ [3]
Error ------------------------------------------------------------------------------------------------- classes.js:23:15
-Cannot extend `React.Component` [1] with `Foo` because object type [2] is incompatible with nullable `$ReadOnly` [3] in
-the first parameter of property `setState`. [incompatible-extend]
+Cannot extend `React.Component` [1] with `Foo` because object type [2] is incompatible with function type [3] in the
+first parameter of property `setState`. Functions without statics are not compatible with objects. [incompatible-extend]
classes.js:23:15
23| setState(o: { y_: string }): void { }
@@ -95,9 +92,9 @@ References:
classes.js:7:19
7| class Foo extends React.Component {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [1]
- /react.js:39:19
+ /react.js:39:49
39| partialState: ?$ReadOnly> | ((State, Props) => ?$ReadOnly>),
- ^^^^^^^^^^^^^^^^^^^^^^^^^^ [3]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [3]
Error ------------------------------------------------------------------------------------------------- classes.js:15:21
diff --git a/tests/react/react.exp b/tests/react/react.exp
index bc524761647..206c2544d22 100644
--- a/tests/react/react.exp
+++ b/tests/react/react.exp
@@ -28,7 +28,7 @@ Error --------------------------------------------------------------------------
Cannot cast `y` to `React.RefSetter` because: [incompatible-cast]
- Either boolean [1] is incompatible with number [2] in the first parameter.
- Or boolean [1] is incompatible with string [3] in the first parameter.
- - Or property `current` is missing in function type [4] but exists in object type [5].
+ - Or function type [4] is incompatible with object type [5]. Functions without statics are not compatible with objects.
contravariant_refsetter.js:12:2
12| (y: React.RefSetter); // ERROR
@@ -1376,7 +1376,7 @@ Error --------------------------------------------------------------------------
Cannot create `Foo` element because in property `ref`: [incompatible-type]
- Either number [1] is incompatible with `Foo` [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
ref.js:10:11
10| {}} />; // Error: `Foo` is not a `number`.
@@ -1456,7 +1456,7 @@ Error --------------------------------------------------------------------------
Cannot create `FooExact` element because in property `ref`: [incompatible-type]
- Either number [1] is incompatible with `FooExact` [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
ref.js:21:16
21| {}} />; // Error: `FooExact` is not a `number`.
@@ -1478,7 +1478,7 @@ Error --------------------------------------------------------------------------
Cannot create `FooExact` element because in property `ref`: [incompatible-type]
- Either `FooExact` [1] is incompatible with null [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
ref.js:22:16
22| {}} />; // Error: `FooExact` may be null.
@@ -1500,7 +1500,7 @@ Error --------------------------------------------------------------------------
Cannot create `FooExact` element because in property `ref`: [incompatible-type]
- Either `FooExact` [1] is incompatible with `Bar` [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
ref.js:24:16
24| {}} />; // Error: `FooExact` is not `Bar`.
@@ -1878,7 +1878,7 @@ Error --------------------------------------------------------------------------
Cannot call `React.useImperativeHandle` with `refSetter` bound to `ref` because: [incompatible-call]
- Either property `focus` is missing in object literal [1] but exists in `Interface` [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
useImperativeHandle_hook.js:32:29
32| React.useImperativeHandle(refSetter, () => ({})); // Error: inexact object literal is incompatible with exact Interface
diff --git a/tests/react_16_3/react_16_3.exp b/tests/react_16_3/react_16_3.exp
index 9aa47602dd9..5ddb197dc7e 100644
--- a/tests/react_16_3/react_16_3.exp
+++ b/tests/react_16_3/react_16_3.exp
@@ -61,7 +61,7 @@ Error --------------------------------------------------------------------------
Cannot create `FancyButton` element because in property `ref`: [incompatible-type]
- Either `HTMLButtonElement` [1] is incompatible with `HTMLDivElement` [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
forwardRef.js:22:38
22| const _g = x} />; // Incorrect ref type
diff --git a/tests/react_16_6/react_16_6.exp b/tests/react_16_6/react_16_6.exp
index 5e5b8a5294f..e3786123676 100644
--- a/tests/react_16_6/react_16_6.exp
+++ b/tests/react_16_6/react_16_6.exp
@@ -80,8 +80,9 @@ References:
Error ---------------------------------------------------------------------------------------------------- lazy.js:11:34
-Cannot call `React.lazy` with function bound to `component` because property `default` is missing in function [1] but
-exists in object type [2] in type argument `R` [3] of the return value. [prop-missing]
+Cannot call `React.lazy` with function bound to `component` because function [1] is incompatible with object type [2] in
+type argument `R` [3] of the return value. Functions without statics are not compatible with objects.
+[incompatible-call]
lazy.js:11:34
11| React.lazy(() => Promise.resolve(FunctionComponent)); // Error property default is missing
diff --git a/tests/react_ref_as_prop/react_ref_as_prop.exp b/tests/react_ref_as_prop/react_ref_as_prop.exp
index 5360aceabd7..66cbcc028e2 100644
--- a/tests/react_ref_as_prop/react_ref_as_prop.exp
+++ b/tests/react_ref_as_prop/react_ref_as_prop.exp
@@ -228,7 +228,7 @@ Error --------------------------------------------------------------------------
Cannot create `FnWithOptionalRefProp` element because in property `ref`: [incompatible-type]
- Either string [1] is incompatible with `HTMLElement` [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
jsx_checking.js:10:39
10| {}} />; // error: string ~> HTMLElement, ref checking still works
@@ -250,7 +250,7 @@ Error --------------------------------------------------------------------------
Cannot create `FnWithRequiredRefProp` element because in property `ref`: [incompatible-type]
- Either string [1] is incompatible with `HTMLElement` [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
jsx_checking.js:12:39
12| {}} />; // error: string ~> HTMLElement, ref checking still works
@@ -305,7 +305,7 @@ Error --------------------------------------------------------------------------
Cannot create `CompWithOptionalRefProp` element because in property `ref`: [incompatible-type]
- Either string [1] is incompatible with `HTMLElement` [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
jsx_checking.js:20:41
20| {}} />; // error: string ~> HTMLElement, ref checking still works
@@ -327,7 +327,7 @@ Error --------------------------------------------------------------------------
Cannot create `CompWithRequiredRefProp` element because in property `ref`: [incompatible-type]
- Either string [1] is incompatible with `HTMLElement` [2] in the first parameter.
- - Or property `current` is missing in function [3] but exists in object type [4].
+ - Or function [3] is incompatible with object type [4]. Functions without statics are not compatible with objects.
jsx_checking.js:22:41
22| {}} />; // error: string ~> HTMLElement, ref checking still works
diff --git a/tests/value_as_type/value_as_type.exp b/tests/value_as_type/value_as_type.exp
index aa230a5045a..1ac88fd0933 100644
--- a/tests/value_as_type/value_as_type.exp
+++ b/tests/value_as_type/value_as_type.exp
@@ -2,7 +2,8 @@ Error --------------------------------------------------------------------------
Cannot create `HocChild` element because in property `ref`: [incompatible-type]
- Either `React.Element` [1] is incompatible with mixed [2] in the first parameter.
- - Or property `current` is missing in property `_handleChild` [3] but exists in object type [4].
+ - Or property `_handleChild` [3] is incompatible with object type [4]. Functions without statics are not compatible
+ with objects.
test1.js:13:45
13| render = (): React.Node => ;