【发布时间】: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 的问题:
- The generics don't work with the type of a key value object #16957
- Cannot use valid union type as a map's key
看起来有一个针对 typescript 3.x 的开放拉取请求:
如果存在此问题的解决方法,我们仍然很感激。
【问题讨论】:
-
嘿,我刚刚测试了你在 TS 3.4 中的最后一次尝试,它工作正常。它确实从泛型类型参数中正确推断出数字类型键。你的解决方案是对的,只是 TS 2.x 不支持它。
-
感谢测试!
标签: typescript typescript-generics