Skip to content

Commit 395f120

Browse files
committed
Allow mixed args to string.prototype.concat()
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>`.
1 parent f9afdbc commit 395f120

File tree

23 files changed

+215
-213
lines changed

23 files changed

+215
-213
lines changed

lib/core.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,9 +1103,11 @@ declare class String {
11031103
codePointAt(index: number): number;
11041104
/**
11051105
* Returns a string that contains the concatenation of two or more strings.
1106-
* @param strings The strings to append to the end of the string.
1106+
* If the arguments are not of the type string, they are converted to string values before
1107+
* concatenating.
1108+
* @param values The values to append to the end of the string.
11071109
*/
1108-
concat(...strings: Array<string>): string;
1110+
concat(...values: Array<mixed>): string;
11091111
constructor(value?: mixed): void;
11101112
/**
11111113
* Returns true if the sequence of elements of searchString converted to a String is the

newtests/autocomplete/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export default (suite(({addFile, flowCmd}) => [
158158
},
159159
{
160160
"name": "concat",
161-
"type": "(...strings: Array<string>) => string"
161+
"type": "(...values: Array<mixed>) => string"
162162
},
163163
{
164164
"name": "endsWith",

tests/async/async.exp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ References:
1010
async.js:11:30
1111
11| async function f1(): Promise<bool> {
1212
^^^^ [2]
13-
<BUILTINS>/core.js:1809:24
14-
1809| declare class Promise<+R> {
13+
<BUILTINS>/core.js:1811:24
14+
1811| declare class Promise<+R> {
1515
^ [3]
1616

1717

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

3838

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

101101
References:
102-
<BUILTINS>/core.js:1809:24
103-
1809| declare class Promise<+R> {
102+
<BUILTINS>/core.js:1811:24
103+
1811| declare class Promise<+R> {
104104
^ [2]
105105

106106

@@ -134,8 +134,8 @@ References:
134134
async_return_void.js:3:32
135135
3| async function foo1(): Promise<string> {
136136
^^^^^^ [2]
137-
<BUILTINS>/core.js:1809:24
138-
1809| declare class Promise<+R> {
137+
<BUILTINS>/core.js:1811:24
138+
1811| declare class Promise<+R> {
139139
^ [3]
140140

141141

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

159159

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

180180

tests/async_iteration/async_iteration.exp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ Cannot cast `result.value` to string because undefined [1] is incompatible with
109109
^^^^^^^^^^^^
110110

111111
References:
112-
<BUILTINS>/core.js:1635:14
113-
1635| +value?: Return,
112+
<BUILTINS>/core.js:1637:14
113+
1637| +value?: Return,
114114
^^^^^^ [1]
115115
return.js:20:20
116116
20| (result.value: string); // error: number | void ~> string

tests/autocomplete/autocomplete.exp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Flags: --pretty
4141
{"name":"charAt","type":"(pos: number) => string"},
4242
{"name":"charCodeAt","type":"(index: number) => number"},
4343
{"name":"codePointAt","type":"(index: number) => number"},
44-
{"name":"concat","type":"(...strings: Array<string>) => string"},
44+
{"name":"concat","type":"(...values: Array<mixed>) => string"},
4545
{
4646
"name":"endsWith",
4747
"type":"(searchString: string, position?: number) => boolean"
@@ -389,7 +389,7 @@ Flags: --pretty
389389
{"name":"charAt","type":"(pos: number) => string"},
390390
{"name":"charCodeAt","type":"(index: number) => number"},
391391
{"name":"codePointAt","type":"(index: number) => number"},
392-
{"name":"concat","type":"(...strings: Array<string>) => string"},
392+
{"name":"concat","type":"(...values: Array<mixed>) => string"},
393393
{
394394
"name":"endsWith",
395395
"type":"(searchString: string, position?: number) => boolean"

tests/core_tests/core_tests.exp

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ Cannot cast `JSON.stringify(...)` to string because undefined [1] is incompatibl
77
^^^^^^^^^^^^^^^^^^^^
88

99
References:
10-
<BUILTINS>/core.js:1627:17
11-
1627| ): string | void;
10+
<BUILTINS>/core.js:1629:17
11+
1629| ): string | void;
1212
^^^^ [1]
1313
json_stringify.js:9:24
1414
9| (JSON.stringify(bad1): string);
@@ -28,11 +28,11 @@ References:
2828
map.js:23:22
2929
23| let x = new Map(['foo', 123]); // error
3030
^^^^^ [1]
31-
<BUILTINS>/core.js:1710:38
32-
1710| constructor(iterable?: ?Iterable<[K, V]>): void;
31+
<BUILTINS>/core.js:1712:38
32+
1712| constructor(iterable?: ?Iterable<[K, V]>): void;
3333
^^^^^^ [2]
34-
<BUILTINS>/core.js:1644:22
35-
1644| interface $Iterator<+Yield,+Return,-Next> {
34+
<BUILTINS>/core.js:1646:22
35+
1646| interface $Iterator<+Yield,+Return,-Next> {
3636
^^^^^ [3]
3737

3838

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

5959

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

7777

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

9595

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

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

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

199199

@@ -209,17 +209,17 @@ property `@@iterator`: [incompatible-call]
209209
^^^^^^^^^
210210

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

225225

@@ -235,17 +235,17 @@ property `@@iterator`: [incompatible-call]
235235
^^^^^^^^^
236236

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

251251

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

262262
References:
263-
<BUILTINS>/core.js:1650:22
264-
1650| interface $Iterable<+Yield,+Return,-Next> {
263+
<BUILTINS>/core.js:1652:22
264+
1652| interface $Iterable<+Yield,+Return,-Next> {
265265
^^^^^ [1]
266266
weakset.js:29:31
267267
29| function* numbers(): Iterable<number> {
268268
^^^^^^ [2]
269-
<BUILTINS>/core.js:1796:26
270-
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
269+
<BUILTINS>/core.js:1798:26
270+
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
271271
^^^^^ [3]
272-
<BUILTINS>/core.js:1796:34
273-
1796| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
272+
<BUILTINS>/core.js:1798:34
273+
1798| declare class WeakSet<T: {...} | $ReadOnlyArray<any>> extends $ReadOnlyWeakSet<T> {
274274
^^^^^^^^^^^^^^^^^^^ [4]
275275

276276

0 commit comments

Comments
 (0)