繁体   English   中英

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

[英]TypeScript: auto-generated dynamic function names

我在 TypeScript 中有一些动态生成的函数名。 我现在可以使用它们的唯一方法是将我的对象转换为<any> 例如: <any>myInstance.getDataA() 这些函数是根据一些规则动态生成的。 基于相同的规则,我想为我的class生成类型定义,但我无法让它工作。

原件.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';
    }
}

我的类.ts

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

我的其他类.ts

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

东西.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'

我想自动生成一个定义文件来定义这些动态属性。

前任。:

我的类.def.ts

 declare interface MyClass {
    getDataA;
    setDataA
 }

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

但是我找不到定义文件的语法来使其工作。 如果我不清楚,请问我,如果您有任何想法,请帮助!

编辑 4.1

使用模板文字类型和映射类型“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;

游乐场链接

4.1之前

内在语言方法

在类型系统中没有办法做到这一点,因为我们不能对字符串文字类型执行字符串操作。 在没有外部工具的情况下,您可以获得的最接近的方法是创建采用字符串文字类型的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

虽然这种方法不是您想要的 100%,但在我们之前的讨论中,目的是让方法具有完整的代码,而这种方法实现了这一点。 如果传入错误的值并获得字符串的完成列表,则会出现错误:

在此处输入图片说明

编译器 API 方法

第二种方法是创建一个自定义工具,使用 typescript 编译器 API来解析 ts 文件,查找从Original派生的类并生成包含方法的接口(在同一文件或不同文件中),如果您有兴趣在这里,我可以编写代码,但这不是微不足道的,虽然编译器 API 是稳定的,但我认为编译器团队并没有像他们对语言所做的那样关心向后兼容性(实际上这是他们的确切声明)在文档页面中制作)。

如果您对这样的解决方案感兴趣,请告诉我,我可以提供它,但我建议不要这样做。

暂无
暂无

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

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