代码之家  ›  专栏  ›  技术社区  ›  Sandy Gifford

带泛型参数的类的类型

  •  2
  • Sandy Gifford  · 技术社区  · 7 年前

    下面是我的代码的简化:

    abstract class Box<T> {
        constructor(protected initialValue: T) {}
    
        public abstract getDefaultThing(): T;
    }
    
    type BoxType = typeof Box;
    
    interface Config {
        boxType: BoxType;
        initialValue: any;
    }
    
    function loadConfig(config: Config) {
        // Need to "as any" this so TSC doesn't complain about abstract class
        return new (config.boxType as any)(config.initialValue);
    }
    

    这里我定义抽象类 Box T initialValue .

    class MyBox extends Box<string> {
        public getDefaultThing(): any {
            return `${this.initialValue} world`;
        }
    }
    
    const config: Config = {
        boxType: MyBox,
        initialValue: "hello",
    };
    
    const loaded = loadConfig(config);
    
    console.log(loaded.getDefaultThing()); // prints "hello world"
    

    这已经不行了- boxType 在里面 config 有一个错误,因为 MyBox . 很好,我真正想做的是重新定义我的 Config 类型检查接口 初始值 BoxType :

    type BoxType<T> = typeof Box<T>;
    
    interface Config<T> {
        boxType: BoxType<T>;
        initialValue: T;
    }
    

    这不管用。。。完全。。。 盒子 但是有没有办法让一个属性成为对一个可实例化泛型类的引用,并缩小到某个泛型类型?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Titian Cernicova-Dragomir    7 年前

    如果你不使用 typeof Box BoxType<T> 作为接受 T 返回一个 Box<T>

    abstract class Box<T> {
        constructor(public initialValue: T) {}
    
        public abstract getDefaultThing(): T;
    }
    
    type BoxType<T> = new (initialValue: T) => Box<T>;
    
    interface Config<T> {
        boxType: BoxType<T>;
        initialValue: any;
    }
    
    function loadConfig<T>(config: Config<T>) {
        return new config.boxType(config.initialValue); // no cast 
    }
    
    class MyBox extends Box<string> {
      public getDefaultThing(): string { // there was a typo here this was any
          return `${this.initialValue} world`;
      }
    }
    
    const config = { // no explcit type needed
      boxType: MyBox,
      initialValue: "hello",
    };
    
    const loaded = loadConfig(config); // loaded is Box<string>
    
    console.log(loaded.getDefaultThing()); // prints "hello world"
    

    loadConfig 返回派生类型而不仅仅是抽象类型(即 MyBox Box<string>

    abstract class Box<T> {
        constructor(public initialValue: T) {}
    
        public abstract getDefaultThing(): T;
    }
    
    type BoxType<T, TBox extends Box<T>> = new (initialValue: T) => TBox;
    
    interface Config<T, TBox extends Box<T>> {
        boxType: BoxType<T, TBox>;
        initialValue: any;
    }
    
    function loadConfig<T, TBox extends Box<T>>(config: Config<T, TBox>) {
        return new config.boxType(config.initialValue); // no cast 
    }
    
    class MyBox extends Box<string> {
      public getDefaultThing(): string { // there was a typo here this was any
          return `${this.initialValue} world`;
      }
    }
    
    const config = { // no explcit type needed
      boxType: MyBox,
      initialValue: "hello",
    };
    
    const loaded = loadConfig(config); // loaded is MyBox
    
    console.log(loaded.getDefaultThing()); // prints "hello world"
    
    推荐文章