Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow array concat to concat arrays of different types #31355

Closed
golopot opened this issue May 12, 2019 · 4 comments
Closed

Allow array concat to concat arrays of different types #31355

golopot opened this issue May 12, 2019 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@golopot
Copy link

golopot commented May 12, 2019

TypeScript Version: 3.5.0-dev.20190511

Code

[0].concat('')
// Argument of type '""' is not assignable to parameter of type 'number | ConcatArray<number>'.

Expected behavior:
The concated array has type (number|string)[].

Actual behavior:
Error.

Possible fix:
In

concat(...items: ConcatArray<T>[]): T[];

interface Array<T> {
- concat(...items: ConcatArray<T>[]): T[];
+ concat<U>(...items: ConcatArray<U>[]): (T|U)[];

Playground Link:
https://www.typescriptlang.org/play/#src=%5B0%5D.concat(%5B''%5D)

Related Issues:
#29604

Search Terms:
array concat

@golopot golopot changed the title Change type of Array.prototype.concat Allow array concat to concat different types May 12, 2019
@golopot golopot changed the title Allow array concat to concat different types Allow array concat to concat arrays of different types May 12, 2019
@jcalz
Copy link
Contributor

jcalz commented May 13, 2019

You can always use declaration merging to add a generic overload to Array.concat() if you find it useful in your own code:

// declaration merge
interface Array<T> {
    concat<U>(...items: (U | ConcatArray<U>)[]): (T | U)[]
}

const okay = [0].concat("");  // Array<string | number>

Playground link

Or, you can widen the array element type yourself before concating to it:

const okay = [0 as string | number].concat(''); // Array<string | number>

Playground link

Before the standard library is modified for everyone, though, you'd want to establish that this use case is common enough in real-world code to warrant it. The compiler tries to catch potential bugs. For real uses of concat() in the wild, what is the false-positive (the compiler thinks good code is a bug) rate of the current typings, and how does that compare to the false-negative (the compiler doesn't catch a bug) rate of the proposed typings?

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label May 13, 2019
@RyanCavanaugh
Copy link
Member

Duplicate #26378

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@Brodzko
Copy link

Brodzko commented May 22, 2019

I have hit this issue while developing a Vue.js component that accepts a value property which can be of type string | string[] | number | number[].

It is an option-list type component that allows a user to select either a single or multiple options from a given list, the options being indexed by string or number ids. The reason I'm not only accepting arrays as the value prop is that the component is bound directly to my form model, which is in turn created automatically from the view model, so keeping proper value type was a requirement.

Within the component however, it is handy to always work with the prop as an array, so I created a simple getter using the `[].concat()' trick. No biggie in vanilla JS but turned out to be an issue with TS. I have dealt with it like so:

get valueArray(): string[] | number[] {  
    return ([] as (string | number)[]).concat(this.value || []) as string[] | number[];  
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants