【问题标题】:Generic method that accepts both { [key: string]: V } and { [key: number]: V } mappings接受 { [key: string]: V } 和 { [key: number]: V } 映射的通用方法
【发布时间】:2019-09-07 12:03:27
【问题描述】:

我想编写一个搜索任何映射的实用程序方法,并且我想强制键类型与谓词类型匹配。

如果有的话,适当的方法签名会是什么样子?

例如,我想概括一下这个签名:

someKey<V>(object: { [key: string]: V }, predicate: (key: string) => boolean): boolean {
   // ....
}

我已经尝试过了,但它给了我一个编译器错误(可能是因为“扩展”),尽管它最能描述我的想法

someKey<K extends string|number, V>(object: { [key: K]: V }, predicate: (key: K) => boolean): boolean {
   // ....
}

以下允许两种类型的地图,但不完全。 IE。它允许谓词运动方法(如 key.startsWith(..))不存在于数字上,但由于自动类型转换而工作,但它禁止使用数字运算符,如 > 或

someKey<V>(object: { [key: string]: V }|{ [key: number]: V }, predicate: (key: string) => boolean): boolean {
   // ....
}

以下允许使用两种类型的映射,但禁止使用 string.startsWith(..) 等方法,尽管它允许使用 > 和

someKey<V>(object: { [key: string]: V }|{ [key: number]: V }, predicate: (key: string|number) => boolean): boolean {
   // ....
}

编辑: 建议的解决方案:

someKey<K extends string|number, V>(object: { [key in keyof K]: V }, predicate: (key: K) => boolean): boolean {
   return true; // your actual logic
}

在使用端引发编译错误(点击放大): 使用 Typescript 2.7.2


编辑: 也试过这个:

someKey<M extends { [key: string]: any } | { [key: number]: any }>
       (object: M, predicate: (key: keyof M) => boolean): boolean {
  return true; // body goes here
}

但如果我这样做:

const testMap2 = {
    1: 'a',
    2: 'bb',
    3: 'ccc',
    4: 'dddd',
    5: 'eeeee',
  };

  it('#someKey should return true if found', () => {
    expect(Utility.someKey(testMap2, key => key > 1)).toBe(true);
  });

上面写着:

(parameter) key: "1" | "2" | "3" | "4" | "5"
Operator '>' cannot be applied to types 'string' and 'number'.ts(2365)

编辑:

存在针对 Typescript 的问题:

看起来有一个针对 typescript 3.x 的开放拉取请求:

如果存在此问题的解决方法,我们仍然很感激。

【问题讨论】:

  • 嘿,我刚刚测试了你在 TS 3.4 中的最后一次尝试,它工作正常。它确实从泛型类型参数中正确推断出数字类型键。你的解决方案是对的,只是 TS 2.x 不支持它。
  • 感谢测试!

标签: typescript typescript-generics


【解决方案1】:

应该是这样的

function someKey<K extends string|number, V>(object: { [key in keyof K]: V }, predicate: (key: K) => boolean): boolean {
    return true; // your actual logic
 }

【讨论】:

  • 不幸的是,这不起作用: const testMap = { 'a': 1, 'bb': 2, 'ccc': 3, 'dddd': 4, 'eeeee': 5, } ; it('#someKey 如果找到应该返回 true', () => { expect(Utility.someKey(testMap, key => key.startsWith('c'))).toBe(true); }); “'{'a': number;'bb': number;'ccc': number;'dddd': number;'eeeeee': number;}' 类型的参数不能分配给'string | number' 类型的参数. type '{ 'a': number; 'bb': number; 'ccc': number; 'dddd': number; 'eeeee': number; }' 不可分配给 type 'number'.ts"
  • @Brixomatic 是不可读的,但是你必须自己实现你的函数体。我只提供了函数签名。
  • 尝试更正格式,但在 cmets 中对我不起作用。使用签名,即使正文为空,也会在用户端提示编译器错误。
  • @Brixomatic 错误是因为有一个空函数体,它什么也不返回。它与函数签名无关。
  • 不。我可以将“未定义”作为函数体返回。使用typescript 2.7.2,可能是TS版本。
猜你喜欢
  • 2021-11-07
  • 2023-03-09
  • 2017-09-14
  • 2020-09-22
  • 2019-08-01
  • 1970-01-01
  • 2013-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多