简体   繁体   English

为什么箭头 function 的隐含“返回”在这种情况下不起作用(TS)?

[英]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 .在撰写本文时,该错误仍然可以在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.如果有人找到一种可靠地复制它的方法,请提供一个 repo,因为我知道一些充满热情的编码人员好奇地寻找它的根本原因。


Initial question最初的问题

I have this JavaScript code, which works:我有这个 JavaScript 代码,它有效:

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:我的第一次 Typescript 尝试非常接近原始 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) 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.由于某种原因,箭头 function () => ({})的隐含return在这里失败。 I need to do () => { return {}; }我需要做() => { return {}; } () => { return {}; } . () => { 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.我已经重写了整件事,我正在使用.reduce()并且我对它很满意。
For the curious types... cripter, actual implementation:对于好奇的类型......cripter,实际实现:

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.但我想了解为什么上面的隐含return失败。

Thanks for taking the time.感谢您抽出宝贵的时间。

The code you have compiles without any errors您编译的代码没有任何错误

在此处输入图像描述

More更多的

For any valid JavaScript Syntax, you will never ever get a SyntaxError if you just copy paste it to a TypeScript file.对于任何有效的 JavaScript 语法,如果您只是将其复制粘贴到 TypeScript 文件,您将永远不会收到 SyntaxError Because TypeScript is syntactically a strict superset of JavaScript syntax因为TypeScript 在语法上是 JavaScript 语法的严格超集

Your TypeScript code is valid and it's correctly transpiled to JS, at least in TS 3.9.2.您的 TypeScript 代码是有效的,并且至少在 TS 3.9.2 中已正确转译为 JS。 It seems to be a jsfiddle bug or a TS bug?.它似乎是一个 jsfiddle 错误或 TS 错误? They use TS 1.7.3 in the jsfiddle you linked to, you can verify by executing ts.version in devtools console.他们在您链接到的 jsfiddle 中使用 TS 1.7.3,您可以通过在 devtools 控制台中执行ts.version来验证。

I added a log breakpoint in the script they use to transpile TS to JS which looks like this:我在他们用来将 TS 转换为 JS 的脚本中添加了一个日志断点,如下所示:

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:记录transpiled变量表明代码已转换为:

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 已转换为:

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.我建议你在 vscode 或ts-node中使用 Quokka 之类的东西,如果你想在本地游乐场尝试一些东西而无需设置东西,但你至少可以控制你正在尝试的 TS 版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM