代码之家  ›  专栏  ›  技术社区  ›  Adam

typescript:自动生成的动态函数名

  •  9
  • Adam  · 技术社区  · 6 年前

    我在typescript中有一些动态生成的函数名。我现在唯一能用的方法就是把我的东西 <any> . 前任。: <any>myInstance.getDataA() 是的。这些函数是根据一些规则动态生成的。基于相同的规则,我希望为自己生成类型定义。 class 是的,但我做不到。

    原件

    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';
        }
    }
    

    我的班级

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

    我的其他班级

    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'
    

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

    前任。:

    我的班级定义

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

    但是我找不到一个语法来让我的定义文件工作。请问我是否不清楚,如果你有任何想法请帮忙!

    1 回复  |  直到 6 年前
        1
  •  5
  •   Titian Cernicova-Dragomir    6 年前

    内部语言方法

    在类型系统中没有办法做到这一点,因为我们不能在字符串文字类型上执行字符串操作。在没有外部工具的情况下,最接近的是 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%,但从我们之前的讨论来看,其目的是使方法的完整代码完成,并且这种方法实现了这一点。如果传入错误的值并获得字符串的完成列表,则会出现错误:

    enter image description here

    编译器api方法

    第二种方法是创建一个使用typescript的自定义工具 compiler API 要分析ts文件,请查找派生自 Original 并生成包含方法的接口(在同一个文件或不同的文件中),如果您感兴趣的话,我可以编写代码,但这不是微不足道的,虽然编译器API是稳定的,但我认为编译器团队不太重视向后兼容性,因为它们与语言有关(事实上,这是他们在文档页中所做的精确声明)。

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