gpt4 book ai didi

typescript - 使用 ES6 集合类型创建和发布 NPM 模块

转载 作者:搜寻专家 更新时间:2023-10-30 21:52:16 25 4
gpt4 key购买 nike

注意:这是我的第一个模块,我想发布自己供其他人使用,因为我觉得它非常有用。它是 TypeScript 的类型化数据序列化引擎。我对这里应该如何做有点迷茫,我需要一个明确的答案。因此,感谢您今天参与进来,让我们开始吧...


我创建了一个使用 ES6 集合类型 SetMapnpm 模块。这些集合类型是:

  • 用于插入我的模块的内部实现
  • 通过我的基于 TypeScript/ES7 装饰器的 API 隐式支持(作为类属性)

内部使用这些类型并没有太大问题,据我所知,我可以通过 package.json 简单地依赖它们,并且在我的来源中导入它们;然后我就准备好了,他们将永远在那里。

另一方面,如果我这样做,我的理解是这些导入将覆盖本地 Map/Set 对象(如果可用),并与我依赖的类型检测(或者这些导入是否会在可用时生成 native 对象?)


关于上面提到的类型检测...最好通过示例 来演示——如果用户要在我的模块中使用Map 对象,这是如何完成:

// Consumer code.
class MapContainer {
@JsonMember
mapValues: Map<number, string>;
}

这就是在我的模块中检测和处理 Map 的方式:

// Internal module code.
// Just for the sake of clarity: 'sourceValue === new MapContainer().mapValues'
if (sourceValue.constructor === Map) {
// Handle 'sourceValue' as a map object...
}

现在很明显这将如何导致冲突。这也是一个反过来的问题:如果用户要 import Map/Set as module 而不是使用 native 可用的实现,我的模块的内部代码将无法识别。

在这种情况下我应该如何定义我的依赖项?

  • 只需在我的代码中插入一些简短的 polyfill,然后让用户以他们可以的任何方式处理它?<​​/li>
  • 使用require('es6-map/implement')? (除了在文档/限制中提及之外,我如何确保我的模块的用户也这样做?)
  • 通过我的源代码中的一些别名导入MapSet,例如__Map__Set,并使用基于字符串的“类名”检测而不是比较构造函数引用? (这看起来很脏)

最佳答案

首先,根据定义,无条件应用自身的 polyfill 并不是真正的 polyfill,而是 hack(例如 zone.js)。行为良好的 polyfill 将使用特征检测,并且仅在全局不存在时才添加。

您基本上有三个选择:

  1. 您可以使用导出其功能的 polyfill,而不是扩充全局。这种技术称为小马填充。它有点武断,因为它并没有真正完成 polyfilling 所做的事情——它不提供原生体验。然而,这样做的好处是您可以正确地依赖于您选择的实现并且您的用户可以依赖于不同的实现并且两者不会干扰。这种方法看起来像

    import Map from 'es6-map'; // pony pure
  2. 如您所述,您可以选择不提交特定的 polyfill,而是简单地记录您的库需要符合 ES2015 的 SetMap 函数存在。然后,您的用户可以从各种 polyfill 中进行选择。这样做的好处是,如果用户想要使用不同的 polyfill,他们可以在不增加代码大小的情况下这样做,这对于针对浏览器的项目来说非常重要。此选项还允许您自己的代码利用可用的 native 实现,而选项 1 无法做到这一点。

  3. 另一种方法是自己简单地对其进行 polyfill。就您自己的代码的结构而言,这是最简单的选择,但也最有可能导致与消费者及其依赖项发生冲突。与选项 2 一样,这具有在可用的情况下使用 native 实现的优势。然而,也有缺点。您将迫使用户支付使用此功能的费用,无论他们是否需要。用户可能不知道您的库是导致 polyfilled Map 在他们的代码中可用的原因,并且可能会隐式地依赖它。您的库相对于其他依赖项的加载顺序可能会导致非常奇怪且难以检测的错误。这种方法看起来像

    import 'es6-map/implement'; // mutate the global

那么它与您的特定用例有何关系?其中大部分适用于任何依赖于可能需要 polyfilling 的功能的库,但正如您所建议的那样,特别相关的部分与别名有关。无需求助于字符串比较。

相反,如果您正在导入 Map 而不是填充它(选项 1. ponyfill 方法),则无法将您在实现中导入的 Map 与捕获的值进行比较来自您家属的代码,因为它将是一个不同的引用,结果通常是 false 并且肯定永远不会可靠。此外,如果您希望它在具有内置 Map 支持的环境中工作,polyfilled 或 native,那么 sourceValue.constructor === Map< 中的 Map 标识符 需要引用该环境中的全局 Map,无论它是什么。

我推荐选项 1,因为它提供了最大的兼容性并允许您正确指定依赖项。这意味着无论你在哪里使用它,都要导入 Map,如

import Map from 'es6-map';

这将创建一个本地。如果您需要在与全局 Map 交互的模块中使用它,那么您需要在别名下导入它,正如您已经考虑的那样。

值得注意的是

sourceValue.constructor === Map

如果全局上没有 Map,将在某些环境中抛出,因此您需要使用类似的东西检查它

typeof Map !== 'undefined' && sourceValue.constructor === Map

为了安全。

与此无关,请将开头的 { 放在需要的同一行。这在 JavaScript 中很重要。

关于typescript - 使用 ES6 集合类型创建和发布 NPM 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41425779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com