【问题标题】:immutables typescript type definitions: why is concat operating on any?不可变的打字稿类型定义:为什么 concat 在任何上运行?
【发布时间】:2017-08-02 08:36:50
【问题描述】:

我不明白为什么the definition of concatCollection<K, V> 中使用any

concat(...valuesOrCollections: Array<any>): Collection<any, any>;

为什么不能:

concat(...valuesOrCollections: Array<V>): Collection<K, V>;

?

【问题讨论】:

  • 也许是因为你可以连接不同类型的数组
  • 可能不会。至少我想要一个额外的类型安全版本。另外,如果不是值类型,键类型 K 至少应该保持不变?
  • (最后@AlekseyL. 非常接近正确答案)

标签: javascript typescript immutable.js


【解决方案1】:

我不确定为什么会这样签名,但您应该可以 augment the module/interface 添加通用签名。
比如:

declare module "immutable" {
    module Collection {
       interface Collection<K, V> {
           concat(...valuesOrCollections: Array<V>): Collection<K, V>;
       }
    }
}

【讨论】:

  • 理想情况下,原始类型定义已经很好了(如果没有人能想出一个很好的理由,我可能会打开它们一个错误)......但我尝试了你的解决方案现在我得到Invalid module name in augmentation, module 'Immutable' cannot be found.。我的 node_modules 中确实有 immutable/dist/immutable.d.ts,它确实包含该模块。我从文件顶部的不可变对象导入:import {Map, List, Seq, Collection} from "immutable";
  • 抱歉,我以为它是作为import ... from "Immutable" 导入的。名称必须相同。在我的回答中将其更改为declare module "immutable"
  • 现在好多了!但是我必须删除扩展语法才能使其工作(也许这就是他们使用any 的原因)——concat(valuesOrCollections: Array&lt;V&gt;): Collection&lt;K, V&gt;。但后来出了点问题。在我退出的Collection 上,我只有一个功能:concat。所以...List(something).concat(...) 对此我只能再次申请concat。因此,它似乎区分了此返回的 Collection(仅包含 concat 的扩展接口)和来自上游库的真实 Collection
  • 您能否将导致问题的代码添加到您的问题中,以便我自己进行测试?
  • 对不起,我们在这里有点偏离主题,所以我创建了一个要点:gist.github.com/emmanueltouzery/… - 这对我来说不编译,我希望它编译。删除模块扩充部分,它可以正常编译。但是是的,我认为不可变的类型定义是错误的,会打开一个错误,等待多一点,以防有人提出解释
【解决方案2】:

好的,所以我尝试修改不可变源中的类型定义并运行测试,现在我明白了为什么他们有他们所做的类型定义。

他们希望基本上支持一切,就像(显然)原始的 JS api。例如添加对象属性:

  it('concats objects to keyed seq', () => {
    let a = Seq({a: 1, b: 2, c: 3});
    let b = {d: 4, e: 5, f: 6};
    expect(a.concat(b).toObject()).toEqual({a: 1, b: 2, c: 3, d: 4, e: 5, f: 6});
  });

直接添加多个值作为参数:

  it('concats values', () => {
    let a = Seq.of(1, 2, 3);
    expect(a.concat(4, 5, 6).size).toBe(6);
    expect(a.concat(4, 5, 6).toArray()).toEqual([1, 2, 3, 4, 5, 6]);
  });

甚至在参数中添加多个数组:

  it('concats multiple arguments', () => {
    let a = Seq.of(1, 2, 3);
    let b = [4, 5, 6];
    let c = [7, 8, 9];
    expect(a.concat(b, c).size).toBe(9);
    expect(a.concat(b, c).toArray()).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
  });

为了在 typescript 中以类型安全的方式实现这一点,我猜我们需要多个重载(concatCollectionconcatValuesconcatProperties 等等)。

PS:公平地说,原始定义中的参数名称是一个很好的提示:valuesOrCollections

更新:在我打开一个小PR后,维护者实现了an exhaustive fully type-safe solution

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
  • 2015-03-23
  • 2019-07-22
相关资源
最近更新 更多