使用ES6集合类型

时间:2017-01-02 11:14:25

标签: typescript npm ecmascript-6 decorator

注意: 这是我想要发布给别人使用的第一个模块,因为我觉得它非常有用。它是TypeScript的类型化数据序列化引擎。我对如何在这里做的事情感到有些迷茫,我需要一个明确的答案。所以,谢谢你今天跳进去,让我们来看看......

我创建了一个使用ES6集合类型npmSet的{​​{1}}模块。这些集合类型是:

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

这些类型的内部使用并没有太大的麻烦,因为据我所知,我可以通过Map简单地依赖它们,并在我的源代码中导入它们;然后我就定了,他们将永远在那里。

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

关于上面提到的类型检测...最好通过示例进行演示 - 如果用户要在我的模块中使用package.json对象,这就是它的方式完成:

Map

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

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

现在很明显这会导致冲突。反过来也是一个问题:如果用户将// Internal module code. // Just for the sake of clarity: 'sourceValue === new MapContainer().mapValues' if (sourceValue.constructor === Map) { // Handle 'sourceValue' as a map object... } 映射/设置为模块而不是使用本机可用实现,则模块的内部代码将无法识别。

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

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

1 个答案:

答案 0 :(得分:1)

首先,根据定义,无条件应用的polyfill实际上不是polyfill,而是hack(例如zone.js)。表现良好的polyfill将使用特征检测,并且只有在尚未存在的情况下才添加全局。

你基本上有三个选择:

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

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

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

    import 'es6-map/implement'; // mutate the global
    
  4. 那么与您的具体用例有何关系?大多数情况适用于任何依赖于可能需要填充的功能的库,但正如您所建议的那样,特定相关的部分与别名相关。 没有必要求助于字符串比较。

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

    我建议使用选项1,因为它提供了最大的兼容性,并允许您正确指定依赖项。 这意味着在{<1}}中导入Map,如

    import Map from 'es6-map';
    

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

    值得注意的是

    sourceValue.constructor === Map
    
    如果全局没有Map

    将会进入某些环境,因此您需要使用类似

    的内容检查
    typeof Map !== 'undefined' && sourceValue.constructor === Map
    

    安全。

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