简体   繁体   English

TypeScript:自动生成的动态函数名称

[英]TypeScript: auto-generated dynamic function names

I have some dynamically generated function names in TypeScript.我在 TypeScript 中有一些动态生成的函数名。 The only way I can use them now is to cast my objects to <any> .我现在可以使用它们的唯一方法是将我的对象转换为<any> Ex.: <any>myInstance.getDataA() .例如: <any>myInstance.getDataA() These functions are dynamically generated based on some rules.这些函数是根据一些规则动态生成的。 Based on the same rules I'd like to generate type-definitions for my class es, but I can not make it work.基于相同的规则,我想为我的class生成类型定义,但我无法让它工作。

original.ts原件.ts

abstract class Original {

    dynamics = ['getData', 'setData'];

    constructor() {
        // I create functions here dynamically
        this.dynamics.forEach((key) => {
            this[key + this.info] = () => null;
        });
    }

    get info() {
        return 'X';
    }
}

my-class.ts我的类.ts

class MyClass extends Original {
    get info() {
        return 'A';
    }
}

my-other-class.ts我的其他类.ts

class MyOtherClass extends Original {
    get info() {
        return 'B';
    }
}

something.ts东西.ts

const myInstance = new MyClass();
console.log(myInstance.getDataA()); // TS2339: Property getDataA does not exist on type: 'MyClass'

const myOtherInstance = new MyOtherClass();
console.log(myInstance.getDataB()); // TS2339: Property getDataB does not exist on type: 'MyClass'

I would like to automatically generate a definition file to define these dynamic properties.我想自动生成一个定义文件来定义这些动态属性。

Ex.:前任。:

my-class.def.ts我的类.def.ts

 declare interface MyClass {
    getDataA;
    setDataA
 }

 //my-other-class.def.ts
 declare interface MyClass {
    getDataB;
    setDataB
 }

But I can not find a syntax for my definition files to make it work.但是我找不到定义文件的语法来使其工作。 Pls ask me if I was not clear, and pls help if you have any idea!如果我不清楚,请问我,如果您有任何想法,请帮助!

Edit for 4.1编辑 4.1

Using Template literal types and mapped type 'as' clauses we can now do concatenate strings in the type system and create a class that has these properties created dynamically.使用模板文字类型和映射类型“as”子句,我们现在可以在类型系统中连接字符串并创建一个具有动态创建的这些属性的类。

function defineDynamicClass<T extends string[]>(...info: T): {
    new (): {
        [K in T[number] as `get${Capitalize<K>}`]: () => unknown
    } & {
        [K in T[number] as `set${Capitalize<K>}`]: (value: unknown) => void
    } & {
        info: T
    }
} {
    return class {
        get info () {
            return info;
        }
    } as any
}
class MyClass extends defineDynamicClass('A', 'B', 'ABAB') {
}
let s =new MyClass();
s.getA();
s.getABAB();
s.setA("")
s.info;

Playground Link 游乐场链接

Before 4.1 4.1之前

The within language approach内在语言方法

There is no way to do this within the type system, since we can't perform string manipulation on string literal types.在类型系统中没有办法做到这一点,因为我们不能对字符串文字类型执行字符串操作。 The closest you can get, without external tools, is to create get/set methods that take a string literal type, that will be of the same as that returned by the getInfo method.在没有外部工具的情况下,您可以获得的最接近的方法是创建采用字符串文字类型的get/set方法,该方法将与getInfo方法返回的相同。

function stringLiteralArray<T extends string>(...v: T[]){ return v;}

abstract class Original {
    get(name: this['info'][number]) {
        return null;
    }

    set(name: this['info'][number], value: any) {
        return null;
    }

    get info() : string[]{
        return [];
    }
}

class MyOtherClass extends Original {
    get info() {
        return stringLiteralArray('A', 'B', 'ABAB');
    }
}
class MyClass extends Original {
    get info() {
        return stringLiteralArray('C', 'D', 'DEDE');
    }
}

let s =new MyClass();
s.get('A') // error 
s.get('C') // ok

While this approach is not 100% what you want, form our previous discussions the aim was to have full code-completion for the methods, and this approach achieves this.虽然这种方法不是您想要的 100%,但在我们之前的讨论中,目的是让方法具有完整的代码,而这种方法实现了这一点。 You get errors if you pass in the wrong value and you get a completion list for the string:如果传入错误的值并获得字符串的完成列表,则会出现错误:

在此处输入图片说明

The compiler API approach编译器 API 方法

A second approach would be to create a custom tool that uses the typescript compiler API to parse the ts files, look for classes derived from Original and generates interfaces containing the methods (either in the same file or a different file) , if you are interested in this I can write the code, but it's not trivial, and while the compiler API is stable I don't think the compiler team takes as much care with backward compatibility as they do with the language (in fact this is the exact statement they make in the documentation page).第二种方法是创建一个自定义工具,使用 typescript 编译器 API来解析 ts 文件,查找从Original派生的类并生成包含方法的接口(在同一文件或不同文件中),如果您有兴趣在这里,我可以编写代码,但这不是微不足道的,虽然编译器 API 是稳定的,但我认为编译器团队并没有像他们对语言所做的那样关心向后兼容性(实际上这是他们的确切声明)在文档页面中制作)。

If you are interested in such a solution, let me know and I can provide it, but I advise against it.如果您对这样的解决方案感兴趣,请告诉我,我可以提供它,但我建议不要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM