tao
tao

Reputation: 90188

Why implied `return` of arrow function doesn't work in this case (TS)?

Update:

At this point, I'm no longer able to repro it on local, after I ran

rm -rf node_mdoules/ && npm i

I'll keep the question, as it might be useful for others experiencing this bug. At the point of this writing, the bug is still reproducible in jsfiddle.

If someone finds a way to repro it reliably, do provide a repo as I know a few passionate coders curious enough to search for its root cause.


Initial question

I have this JavaScript code, which works:

const iconsMap = new Map([
  ['Roofs', 'roofs'],
  ['Walls', 'walls'],
  ['Windows & Doors', 'doors'],
  ['Heating & Controls', 'heating'],
  ['Ventilation & Air Tightness', 'ventilation'],
  ['Renewables', 'renewables'],
  ['Others', 'others'],
  ['Default', 'home'],
]);

console.log(
  Object.assign({}, ...Array.from(iconsMap).map(([label, fileName]) => ({[label]: fileName})))
);

My first Typescript attempt was very close to original JS:

const iconsMap: Map<string, string> = new Map([
      ['Roofs', 'roofs'],
      ['Walls', 'walls'],
      ['Windows & Doors', 'doors'],
      ['Heating & Controls', 'heating'],
      ['Ventilation & Air Tightness', 'ventilation'],
      ['Renewables', 'renewables'],
      ['Others', 'others'],
      ['Default', 'home'],
    ]);
    
interface Dictionary<T> {
  [key: string]: T;
}

console.log(
  Object.assign(
    {} as Dictionary<string>,
    ...Array.from(iconsMap).map(
      ([label, fileName]) => ({ [label]: fileName })
    )
  )
);

But it breaks with:

VM325:13 Uncaught SyntaxError: Unexpected token '(' at new Function () at exec (VM319 typescript.js:41)

For some reason, the implied return of arrow function () => ({}) fails here. I need to do () => { return {}; }. So this works:

console.log(
  Object.assign(
    {} as Dictionary<string>,
    ...Array.from(iconsMap).map(([label, fileName]) => {
      return { [label]: fileName };
    })
  )
);

Could anyone explain why?

Note: I'm not interested in alternative ways to rewrite the above code (it's actually taken out of context to highlight the issue). I already re-rewrote the whole thing, I'm using a .reduce() and I'm happy enough with it.
For the curious types... cripter, actual implementation:

export const iconRegistry: Dictionary<string> = Array.from(iconsMap)
  .reduce((o, [label, fileName]) => ({
    ...o,
    [label]: require(`./assets/icons/measure/${fileName}.svg`)
  }), {} as Dictionary<string>);

But I'd like to understand why the implied return fails above.

Thanks for taking the time.

Upvotes: 2

Views: 178

Answers (2)

user9152616
user9152616

Reputation:

Your TypeScript code is valid and it's correctly transpiled to JS, at least in TS 3.9.2. It seems to be a jsfiddle bug or a TS bug?. They use TS 1.7.3 in the jsfiddle you linked to, you can verify by executing ts.version in devtools console.

I added a log breakpoint in the script they use to transpile TS to JS which looks like this:

var transpiled = ts.transpile.apply(ts, [param[0], param[1], "filename", diagnostics]);
new Function(transpiled)();

Logging the transpiled variable shows that the code was transformed to this:

var iconsMap = new Map([
    ['Roofs', 'roofs'],
    ['Walls', 'walls'],
    ['Windows & Doors', 'doors'],
    ['Heating & Controls', 'heating'],
    ['Ventilation & Air Tightness', 'ventilation'],
    ['Renewables', 'renewables'],
    ['Others', 'others'],
    ['Default', 'home'],
]);
console.log(Object.assign({}, ...Array.from(iconsMap).map(function ([label, fileName]) ({ [label]: fileName }))));

Notice that the arrow function was transformed to:

function ([label, fileName]) ({ [label]: fileName })))

Which, of course, is invalid. I'd suggest you to use something like Quokka in vscode or ts-node if you want some local playground to try out things without having to setup stuff but you can, at least, have control over the TS version you're trying.

Upvotes: 1

basarat
basarat

Reputation: 276085

The code you have compiles without any errors

enter image description here

More

For any valid JavaScript Syntax, you will never ever get a SyntaxError if you just copy paste it to a TypeScript file. Because TypeScript is syntactically a strict superset of JavaScript syntax

Upvotes: 3

Related Questions