TypeScript Version: nightly ( 2.1.0-dev.20160822)
Code
With --strictNullChecks
// A *self-contained* demonstration of the problem follows...
let arg: any[] = [""];
let rootNodesOrAppElements = [].concat(arg);
I get
./node_modules/.bin/tsc
t.ts(3,40): error TS2345: Argument of type 'any[]' is not assignable to parameter of type 'never[]'.
Type 'any' is not assignable to type 'never'.
I binary searched the releases - this happens with [email protected] but not with [email protected]
the problem is an empty array with no contextual type ([] in [].concat(arg)) is inferred as never[] under strictNullChecks. and never is not assignable from any other type.
([] as any[]).concat(arg); should do the trick
thanks!
Out of curiosity, do we think this is desirable behavior? I feel like [].concat is a fairly standard JS idiom.
The issue is what is the element type of [] if there is no contextual type? undefined seems reasonable since there is not a better source of information available. This works in in non strict null checks mode because undefined is in the domain of all types, and gets widened to any. in stictNullChecks it does not, since undefined is not any other type except undefined; and in that sense, never is a better name for this condition. so it is not never that is the issue.
@mhegazy I usually use concat to convert a single element or emblems array to array shape, e.g.:
function makeList<T> (singleOrArray: T | Array<T>): Array<T> {
return ([] as Array<T>).concat(singleOrArray)
}
as @evmar said, using literal [] is a fairly common usage. Maybe less rescrtictions on assert its type will be better.
Why would you jump through those hoops? If you are constructing an array, construct an array.
const arr = new Array(something);
The only _hole_ in that is that if something is a number, but that was why Array.from() was introduced. While [].concat() might be in wide usage, it is a horribly inefficient construct, because it creates an array literal, then allocates another array to append the items onto it. You also have the ability to author new arrays with the spread operator [ ...items ] which will give accurate typings.
If you don't like being explicit about your types, don't use strict mode, but please don't dumb down strict mode for the rest of us.
@kitsonk If new Array(something) receive an array, it produces a two dimensions array. 'concat' does the right thing. The inconsistency with usage below just looks weird.
function makeList<T> (singleOrArray: T | Array<T>): Array<T> {
return Array.prototype.concat.call([], singleOrArray)
}
Most helpful comment
the problem is an empty array with no contextual type (
[]in[].concat(arg)) is inferred asnever[]under strictNullChecks. andneveris not assignable from any other type.([] as any[]).concat(arg);should do the trick