我想将函数字符串名称传递给函数, 所以我可以这样使用它:
function processArrayObjectPropName<T extends IkeyOfObject>(items: T[], methodName: string = 'toLowerCase'): T[] {
for (const item of items) {
const keys: string[] = Object.keys(item);
let keyCount: number = keys.length;
while (keyCount--) {
const key: string = keys[keyCount];
item[key[methodName]()] = item[key]; //throw an error
}
}
return items;
}
但是,tsc给了我这个错误:
Error:(38, 16) TS7015:Element implicitly has an 'any' type because index expression is not of type 'number'.
答案 0 :(得分:1)
key
是一个字符串,methodName
也是一个字符串,表达式key[methodName]
将使用一个字符串来索引另一个字符串,这就是您收到错误的原因。
我无法弄清楚你想要实现的目标。将对象的所有键复制到这些键的小写(或其他错位)版本?那可能是:
item[(key as any)[methodName]()] = item[key];
将key
转换为any
类型允许您下标字符串,从而间接获取其方法。
答案 1 :(得分:1)
TL; DR:使用标有Solution
的代码段。
错误消息有意义,因为当您尝试运行key[methodName]
时,它实际上会调用String.prototype.operator[]
,签名为readonly [index: number]: string;
。
由于methodName
这里是string
而不是number
,因此会根据其签名提供警告信息。
我们在这里可以做的是使methodName
更具体,因此TypeScript知道key[methodName]
在任何情况下都不会返回null
。
function processArrayObjectPropName<T extends IkeyOfObject>
(items: T[], methodName: keyof String = 'toLowerCase'): T[] {
现在,TypeScript会发出另一个警告,因为不同函数的参数数量可能不同。
[ts] Cannot invoke an expression whose type lacks a call signature. Type 'number | (() => string) | ((pos: number) => string) | ((index: number) => number) | ((...strings:...' has no compatible call signatures.
因此我们需要使methodName
的类型规范更加具体,确保它只包含函数接受0参数;
通过这种方式,我们会有类似的东西,编译:
// Solution 1
type StringMethodWithZeroParameter = 'toLowerCase' | 'toUpperCase'
function processArrayObjectPropName<T extends IkeyOfObject>
(items: T[], methodName: StringMethodWithZeroParameter = 'toLowerCase'): T[] {
同时,如果可以更改签名,则可以使用lambda而不是函数名称进行传递。
// Solution 2
processArrayObjectPropName(items, String.prototype.toLowerCase);
function processArrayObjectPropName<T extends IkeyOfObject>(items: T[], transformer: (i: string) => string): T[] {
for (const item of items) {
const keys: string[] = Object.keys(item);
let keyCount: number = keys.length;
while (keyCount--) {
const key: string = keys[keyCount];
item[transformer(key)] = item[key];
}
}
return items;
}