2

I have a dead simple component. Works perfectly in javascript.

const Test = (props: any) => <div>{props.children}</div>;

const Root: React.SFC<{}> = props => {
  return (
    <div className="Root">
      <h1>hello world.</h1>
      <Test>{[...Array(20)].map((_, index) => <h1>test{index}</h1>)}</Test>
    </div>
  );
};

export default Root;

But doesn't work in typescript. Why?

Both use same React version.

EDIT:

TypeScript: https://codepen.io/anon/pen/eKGoWo

JavaScript: https://codepen.io/anon/pen/GGMLOv

J. Reku
  • 509
  • 1
  • 5
  • 15

1 Answers1

3

It works if you change it from that spread array map to

<Test>{Array.from({length:20}, (_, index) => <h1 key={index}>test{index}</h1>)}</Test>

(I also added key to that, since React complains once it starts working. :-) )

Not working: https://codepen.io/anon/pen/XYeQzv?editors=1010

Working: https://codepen.io/anon/pen/eKGoya?editors=1010

It has to do with how TypeScript transpiles that spread notation. TypeScript is converting that [...Array(20)].map(/*...*/) to this:

Array(5).slice().map(/*...*/)

The problem with that is that Array(20) creates an array of length 20 with no entries in it. slice replicates that. map only visits entries that actually exist in the array, not gaps. But [...Array(20)] creates an array with 20 entries containing undefined, which map will visit:

const a1 = [...Array(5)];
console.log(0 in a1);   // true
const a1m = a1.map((_, index) => index);
console.log(0 in a1m);  // true
console.log(a1m);       // 0, 1, 2, 3, 4

const a2 = Array(5).slice();
console.log(0 in a2);   // false
const a2m = a2.map((_, index) => index);
console.log(0 in a2m);  // false
console.log(a2m);       // (gaps)
Look in the real console (the snippet console gives the impression values exist in the array when they don't).

Yury Tarabanko kindly found a bug report for it.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • thanks, but this is ridicilous of TypeScript, i can't believe something as simple as a spread operator isn't working as expected. – J. Reku Jun 16 '18 at 12:03
  • @J.Reku - I've figured out why now (see edit), and it's definitely not a faithful emulation of spread. It may be worth having a nose around to see if there's a setting for being pure vs. being fast or something (a couple of Babel plugins have those settings, compromising correctness for performance in a couple of cases). If you don't find such a setting, may be worth reporting as a bug. – T.J. Crowder Jun 16 '18 at 12:08
  • @J.Reku - No need, Yury [found a bug report](https://stackoverflow.com/questions/50887560/why-are-these-children-as-array-not-rendered-in-ts/50887699#comment88776913_50887560) already there. – T.J. Crowder Jun 16 '18 at 12:12