Skip to content

Commit

Permalink
Allow mixed args to string.prototype.concat()
Browse files Browse the repository at this point in the history
According to MDN docs for the `concat()` method of the `String` type:

> If the arguments are not of the type string, they are converted to string
> values before concatenating.

Passing numbers, objects, etc to `String.prototype.concat` is is valid JS
behavior but currently causes an error in Flow. It also may be blocking
facebook/react#22064.

This commit changes the arg type: `Array<string>` -> `Array<mixed>`.
  • Loading branch information
justingrant committed Aug 17, 2021
1 parent f9afdbc commit 395f120
Show file tree
Hide file tree
Showing 23 changed files with 215 additions and 213 deletions.
6 changes: 4 additions & 2 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -1103,9 +1103,11 @@ declare class String {
codePointAt(index: number): number;
/**
* Returns a string that contains the concatenation of two or more strings.
* @param strings The strings to append to the end of the string.
* If the arguments are not of the type string, they are converted to string values before
* concatenating.
* @param values The values to append to the end of the string.
*/
concat(...strings: Array<string>): string;
concat(...values: Array<mixed>): string;
constructor(value?: mixed): void;
/**
* Returns true if the sequence of elements of searchString converted to a String is the
Expand Down
2 changes: 1 addition & 1 deletion newtests/autocomplete/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export default (suite(({addFile, flowCmd}) => [
},
{
"name": "concat",
"type": "(...strings: Array<string>) => string"
"type": "(...values: Array<mixed>) => string"
},
{
"name": "endsWith",
Expand Down
24 changes: 12 additions & 12 deletions tests/async/async.exp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ References:
async.js:11:30
11| async function f1(): Promise<bool> {
^^^^ [2]
<BUILTINS>/core.js:1809:24
1809| declare class Promise<+R> {
<BUILTINS>/core.js:1811:24
1811| declare class Promise<+R> {
^ [3]


Expand All @@ -31,8 +31,8 @@ References:
async.js:30:48
30| async function f4(p: Promise<number>): Promise<bool> {
^^^^ [2]
<BUILTINS>/core.js:1809:24
1809| declare class Promise<+R> {
<BUILTINS>/core.js:1811:24
1811| declare class Promise<+R> {
^ [3]


Expand Down Expand Up @@ -99,8 +99,8 @@ undefined in type argument `R` [2]. [incompatible-return]
^^^^^^ [1]

References:
<BUILTINS>/core.js:1809:24
1809| declare class Promise<+R> {
<BUILTINS>/core.js:1811:24
1811| declare class Promise<+R> {
^ [2]


Expand Down Expand Up @@ -134,8 +134,8 @@ References:
async_return_void.js:3:32
3| async function foo1(): Promise<string> {
^^^^^^ [2]
<BUILTINS>/core.js:1809:24
1809| declare class Promise<+R> {
<BUILTINS>/core.js:1811:24
1811| declare class Promise<+R> {
^ [3]


Expand All @@ -152,8 +152,8 @@ References:
async_return_void.js:7:32
7| async function foo2(): Promise<string> {
^^^^^^ [2]
<BUILTINS>/core.js:1809:24
1809| declare class Promise<+R> {
<BUILTINS>/core.js:1811:24
1811| declare class Promise<+R> {
^ [3]


Expand All @@ -173,8 +173,8 @@ References:
async_return_void.js:11:32
11| async function foo3(): Promise<string> {
^^^^^^ [2]
<BUILTINS>/core.js:1809:24
1809| declare class Promise<+R> {
<BUILTINS>/core.js:1811:24
1811| declare class Promise<+R> {
^ [3]


Expand Down
4 changes: 2 additions & 2 deletions tests/async_iteration/async_iteration.exp
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ Cannot cast `result.value` to string because undefined [1] is incompatible with
^^^^^^^^^^^^

References:
<BUILTINS>/core.js:1635:14
1635| +value?: Return,
<BUILTINS>/core.js:1637:14
1637| +value?: Return,
^^^^^^ [1]
return.js:20:20
20| (result.value: string); // error: number | void ~> string
Expand Down
4 changes: 2 additions & 2 deletions tests/autocomplete/autocomplete.exp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Flags: --pretty
{"name":"charAt","type":"(pos: number) => string"},
{"name":"charCodeAt","type":"(index: number) => number"},
{"name":"codePointAt","type":"(index: number) => number"},
{"name":"concat","type":"(...strings: Array<string>) => string"},
{"name":"concat","type":"(...values: Array<mixed>) => string"},
{
"name":"endsWith",
"type":"(searchString: string, position?: number) => boolean"
Expand Down Expand Up @@ -389,7 +389,7 @@ Flags: --pretty
{"name":"charAt","type":"(pos: number) => string"},
{"name":"charCodeAt","type":"(index: number) => number"},
{"name":"codePointAt","type":"(index: number) => number"},
{"name":"concat","type":"(...strings: Array<string>) => string"},
{"name":"concat","type":"(...values: Array<mixed>) => string"},
{
"name":"endsWith",
"type":"(searchString: string, position?: number) => boolean"
Expand Down
80 changes: 40 additions & 40 deletions tests/core_tests/core_tests.exp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Cannot cast `JSON.stringify(...)` to string because undefined [1] is incompatibl
^^^^^^^^^^^^^^^^^^^^

References:
<BUILTINS>/core.js:1627:17
1627| ): string | void;
<BUILTINS>/core.js:1629:17
1629| ): string | void;
^^^^ [1]
json_stringify.js:9:24
9| (JSON.stringify(bad1): string);
Expand All @@ -28,11 +28,11 @@ References:
map.js:23:22
23| let x = new Map(['foo', 123]); // error
^^^^^ [1]
<BUILTINS>/core.js:1710:38
1710| constructor(iterable?: ?Iterable<[K, V]>): void;
<BUILTINS>/core.js:1712:38
1712| constructor(iterable?: ?Iterable<[K, V]>): void;
^^^^^^ [2]
<BUILTINS>/core.js:1644:22
1644| interface $Iterator<+Yield,+Return,-Next> {
<BUILTINS>/core.js:1646:22
1646| interface $Iterator<+Yield,+Return,-Next> {
^^^^^ [3]


Expand All @@ -49,11 +49,11 @@ References:
map.js:23:29
23| let x = new Map(['foo', 123]); // error
^^^ [1]
<BUILTINS>/core.js:1710:38
1710| constructor(iterable?: ?Iterable<[K, V]>): void;
<BUILTINS>/core.js:1712:38
1712| constructor(iterable?: ?Iterable<[K, V]>): void;
^^^^^^ [2]
<BUILTINS>/core.js:1644:22
1644| interface $Iterator<+Yield,+Return,-Next> {
<BUILTINS>/core.js:1646:22
1646| interface $Iterator<+Yield,+Return,-Next> {
^^^^^ [3]


Expand All @@ -70,8 +70,8 @@ References:
map.js:24:16
24| let y: Map<number, string> = new Map([['foo', 123]]); // error
^^^^^^ [2]
<BUILTINS>/core.js:1708:19
1708| declare class Map<K, V> extends $ReadOnlyMap<K, V> {
<BUILTINS>/core.js:1710:19
1710| declare class Map<K, V> extends $ReadOnlyMap<K, V> {
^ [3]


Expand All @@ -88,8 +88,8 @@ References:
map.js:24:24
24| let y: Map<number, string> = new Map([['foo', 123]]); // error
^^^^^^ [2]
<BUILTINS>/core.js:1708:22
1708| declare class Map<K, V> extends $ReadOnlyMap<K, V> {
<BUILTINS>/core.js:1710:22
1710| declare class Map<K, V> extends $ReadOnlyMap<K, V> {
^ [3]


Expand All @@ -102,8 +102,8 @@ Cannot cast `x.get(...)` to boolean because undefined [1] is incompatible with b
^^^^^^^^^^^^

References:
<BUILTINS>/core.js:1718:22
1718| get(key: K): V | void;
<BUILTINS>/core.js:1720:22
1720| get(key: K): V | void;
^^^^ [1]
map.js:29:20
29| (x.get('foo'): boolean); // error, string | void
Expand Down Expand Up @@ -183,17 +183,17 @@ property `@@iterator`: [incompatible-call]
^^^^^^^^^

References:
<BUILTINS>/core.js:1644:22
1644| interface $Iterator<+Yield,+Return,-Next> {
<BUILTINS>/core.js:1646:22
1646| interface $Iterator<+Yield,+Return,-Next> {
^^^^^ [1]
weakset.js:19:24
19| let ws3 = new WeakSet([1, 2, 3]); // error, must be objects
^ [2]
<BUILTINS>/core.js:1796:26
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
<BUILTINS>/core.js:1798:26
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
^^^^^ [3]
<BUILTINS>/core.js:1796:34
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
<BUILTINS>/core.js:1798:34
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
^^^^^^^^^^^^^^^^^^^ [4]


Expand All @@ -209,17 +209,17 @@ property `@@iterator`: [incompatible-call]
^^^^^^^^^

References:
<BUILTINS>/core.js:1644:22
1644| interface $Iterator<+Yield,+Return,-Next> {
<BUILTINS>/core.js:1646:22
1646| interface $Iterator<+Yield,+Return,-Next> {
^^^^^ [1]
weakset.js:19:27
19| let ws3 = new WeakSet([1, 2, 3]); // error, must be objects
^ [2]
<BUILTINS>/core.js:1796:26
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
<BUILTINS>/core.js:1798:26
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
^^^^^ [3]
<BUILTINS>/core.js:1796:34
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
<BUILTINS>/core.js:1798:34
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
^^^^^^^^^^^^^^^^^^^ [4]


Expand All @@ -235,17 +235,17 @@ property `@@iterator`: [incompatible-call]
^^^^^^^^^

References:
<BUILTINS>/core.js:1644:22
1644| interface $Iterator<+Yield,+Return,-Next> {
<BUILTINS>/core.js:1646:22
1646| interface $Iterator<+Yield,+Return,-Next> {
^^^^^ [1]
weakset.js:19:30
19| let ws3 = new WeakSet([1, 2, 3]); // error, must be objects
^ [2]
<BUILTINS>/core.js:1796:26
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
<BUILTINS>/core.js:1798:26
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
^^^^^ [3]
<BUILTINS>/core.js:1796:34
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
<BUILTINS>/core.js:1798:34
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
^^^^^^^^^^^^^^^^^^^ [4]


Expand All @@ -260,17 +260,17 @@ Cannot call `WeakSet` with `numbers()` bound to `iterable` because in type argum
^^^^^^^^^

References:
<BUILTINS>/core.js:1650:22
1650| interface $Iterable<+Yield,+Return,-Next> {
<BUILTINS>/core.js:1652:22
1652| interface $Iterable<+Yield,+Return,-Next> {
^^^^^ [1]
weakset.js:29:31
29| function* numbers(): Iterable<number> {
^^^^^^ [2]
<BUILTINS>/core.js:1796:26
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
<BUILTINS>/core.js:1798:26
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
^^^^^ [3]
<BUILTINS>/core.js:1796:34
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
<BUILTINS>/core.js:1798:34
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
^^^^^^^^^^^^^^^^^^^ [4]


Expand Down
Loading

0 comments on commit 395f120

Please sign in to comment.