Typescript:通过索引对类函数进行类型化访问

mw3dktmi  于 2023-05-19  发布在  TypeScript
关注(0)|答案(2)|浏览(146)

我需要根据DataValues类的字段名称调用ExampleOne类的函数,从那里获取值并将它们传递给ExampleOne类示例的函数
告诉我如何通过索引器正确地编写函数调用,正如您所看到的,类型存在一些问题

class ExampleOne {
    f1(argStr: string): string {
        return `some text ${argStr}`;
    }
    f2(argNumber: number): string {
        return  `some text ${argNumber}`;
    }
}

class DataValues {
    f1: number = 64;
    f2: string = 'Hello';
}

function example() {
    const testClass = new ExampleOne();
    const data = new DataValues();

    for (const [key, value] of Object.entries(data)) {
        const functionName = key as keyof ExampleOne;
        const func = testClass[functionName];

        const arg: number | string = value;

        const result = func.apply(testClass, [arg]); 
/*                       | <---------- error this*
                         |
                         |
The 'this' context of type 
'((argStr: string) => string) | ((argNumber: number) => string)' 
is not assignable to method's 'this' of type 
'(this: ExampleOne, argStr: string) => string'.
Type '(argNumber: number) => string' is not assignable to type 
'(this: ExampleOne, argStr: string) => string'.
Types of parameters 'argNumber' and 'argStr' are incompatible.
Type 'string' is not assignable to type 'number'.(2684) */

    console.log(result);
    }
}

example();

Playground链接
最初我尝试这样做,但它没有工作:

for (const [key, value] of Object.entries(data)) {
        const functionName = key as keyof ExampleOne;
        const func = testClass[functionName];

        const arg: number | string = value;

        const result = testClass[functionName](arg);
/*                                              | <--- error this
                                                |
                                                |
Argument of type 'string | number' is not assignable to parameter of type 'never'.
  Type 'string' is not assignable to type 'never'.(2345)
*/

    console.log(result);
    }
ryevplcw

ryevplcw1#

type FunctionCollection<V> = {
    [K in keyof V]: (_: V[K]) => string;
}

function applyFunctions<V>(fc: FunctionCollection<V>, dv: V): void {
    for (let key in dv) {
        console.log(fc[key](dv[key]));
    }
}

  /////////////
 // Example //
/////////////

class Values {
    f1: string = 'Hello';
    f2: number = 64;
}

class Functions {
    f1(argStr: string): string {
        return `some text ${argStr}`;
    }
    f2(argNumber: number): string {
        return  `some text ${argNumber}`;
    }
}

function example() {
    applyFunctions<Values>(new Functions(), new Values());
}

Playground

djmepvbi

djmepvbi2#

对于任何和我有类似问题的人(我想调用所有函数,而不仅仅是那些我知道参数的函数)和如果你愿意在.js文件中放置一些代码:
这就是你如何获得一个类中的所有函数名:

const classObject = new MyClass();
    const functionNames = Object.getOwnPropertyNames(classObject.__proto__);

通过这样做,可以调用类中的任何函数

classObject[functionName](value);

在可能的情况下,我会说@md2perpe的答案是上级的,因为它更简洁,参数意识和有效的 typescript !.
但是,您可以使用此技术调用所有带参数的函数。下面是一个示例:

function convertObjectToDictionary(obj) {
    return Object.keys(obj).reduce((result, key) => {
        result[key] = obj[key];
        return result;
    }, {});
}

function RunAllFunctionsInClassWithValues(
    classObject,
    parameterOverrides,
) {
    const functionNames = Object.getOwnPropertyNames(classObject.__proto__);
    const paramDict = convertObjectToDictionary(parameterOverrides);
    
    for (let i = 0; i < functionNames.length; i++) {
        let functionName = functionNames[i];

        if (functionName !== 'constructor') {
            
            try {               
                value = paramDict[functionName];
        
                classObject[functionName](value);
            } catch (e) {
                success = false;
                errorMessage = e.message;
            }

        }
    }
}

class MyClass
{
  Speak(text)
  {
    console.log(text);
  }
  QuackNTimes(number)
  {
    for (let i = 0; i < number; i++) 
        this.Speak(`Quack ${i}`);
  }
  Bark()
  {
     console.log("Woof");
  }
}

class MyParameters
{
    Speak = "Hello World";
    QuackNTimes = 4;
}

RunAllFunctionsInClassWithValues( new MyClass(), new MyParameters())

我想知道这是否可以改进,成为有效的 typescript !然而,你也可以在这里利用JS的奇特之处:可选参数等

相关问题