【问题标题】:preact-cli/babel/typescript - getting Symbol.iterator and [...spread] to work correctlypreact-cli/babel/typescript - 让 Symbol.iterator 和 [...spread] 正常工作
【发布时间】:2021-01-25 14:08:28
【问题描述】:

在我的代码中,我有一个名为range 的函数,它产生范围。实现如下:

export const range = (min: number, max: number) => {
    // ...

    return {
        // ...
        *[Symbol.iterator]() {
            let n = min

            while (n <= max) yield n++
        }
    }
}

Array.from(range(1, 5)) 提供[1, 2, 3, 4, 5],正如您所料。但是,[...range(1, 5)] 给出了[{[Symbol.iterator]: ƒ}](长度为 1 的数组,包含范围对象),这显然是不正确的。如果我将range 附加到window 对象并从浏览器控制台调用它,[...range(1, 5)] 将提供[1, 2, 3, 4, 5],正如预期的那样。

在进一步调试后,扩展运算符似乎被转译为:

// console.log(() => [...range(1, 5)])
ƒ () { return [].concat(range(1, 5)) }

如果传播的是一个数组,这将可以正常工作,但对于其他类型的可迭代对象则失败。

.tsconfig 与我之前使用的相同,针对ESNext,并将downlevelIteration 更改为truefalse 没有任何作用,所以我相当有信心问题不存在.

看起来这与 Babel 有关,但我不知道如何正确配置它。旧版浏览器支持不是什么大问题 - 如果它适用于最新的 Chromium 和 Firefox,我很高兴。

package.json:

"browserslist": "last 3 chrome versions, last 3 firefox versions"

.babelrc:

{ "presets": [ [ "preact-cli/babel", { "modules": "commonjs" } ] ] }

preact.config.js 与此处的相同:preact.config.js permalink。以下是相关部分:

webpack(config, env, helpers, options) {
    // ...

    config.module.rules = config.module.rules.map(rule => {
        if (rule.loader === 'babel-loader') {
            const use = [
                {
                    loader: 'babel-loader',
                    options: rule.options
                },
                {
                    loader: 'ts-loader'
                }
            ]

            return {
                ...rule,
                loader: undefined,
                options: undefined,
                use,
            }
        }
        // ...    
    })
    // ...
}

我将如何解决这个问题?

【问题讨论】:

  • "downlevelIteration": true 似乎解决了我这边的问题:codesandbox.io/s/async-bush-ns3y7?file=/src/index.ts
  • @PeterLehnhardt 该应用使用 Parcel,而不是 Webpack、Babel 和 Preact。问题肯定出在构建工具上,而不是代码上。
  • @是的,你是对的。我稍微抬头一看,发现this。你试过了吗?

标签: javascript typescript webpack babeljs preact


【解决方案1】:

最终通过完全删除babel-loader 解决了这个问题。我用这个替换了preact.config.js的相关部分:

if (rule.loader === 'babel-loader') {
    return { loader: 'ts-loader' }
}

不过,我仍然很想知道如何在不完全移除 Babel 的情况下解决此问题

【讨论】:

  • @PeterLehnhardt 在他的评论中指出了必要的配置。这不是真正的答案,而是不必要的解决方法。
  • 我的问题是“我该如何解决这个问题”,自我回答,因为它解决了我的问题并完美地适合我的用例(仅限现代浏览器)。我不认为这是一种解决方法,因为我一开始就不需要 Babel。我也在@PeterLehnhard 的第二条评论之前发布了这个(这可能是一个更好的通用解决方案,即使不是针对我的具体情况)。
【解决方案2】:

我将在 cmets 中重复 @PeterLehnhardt 提供的解决方案,以便每个人都可以看到它: 创建 preact.config.js

export default {
  webpack(config, env, helpers, options) {
    const { rule } = helpers.getLoadersByName(config, 'babel-loader')[0];
    const babelConfig = rule.options;

    babelConfig.assumptions = {
      iterableIsArray: false, 
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-27
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 2017-10-27
    • 2016-05-16
    • 2016-03-12
    相关资源
    最近更新 更多