javascript - 如何在基类代码内引用 `this.constructor` 上的静态属性?

标签 javascript generics typescript

我有这样的 TypeScript (JavaScript) 类:

import * as React from 'react'

export default
class StyleableComponent<PROPS, STATE> extends React.Component<PROPS, STATE> {
    protected classes: any
    static style: any

    someMethod() {
        const ctor = this.constructor
        console.log(this.constructor.style)
    }
}

并且 TypeScript 抛出此错误:

ERROR in ./src/StyleableComponent.ts
(11,38): error TS2339: Property 'style' does not exist on type 'Function'.

但是,显然,您可以看到在类定义中声明了static style:any

那么,我们如何正确使用 this.constructor 呢?请注意,this.constructor 可以是扩展 StyleableComponent 的类的构造函数,因此 this.constructor 可能不是 === StyleableComponent,但它应该具有 style 属性,因为它继承自 StyleableComponent

例如,

interface P {...}
interface S {...}
class Foo extends StyleableComponent<P,S> {...}

console.log(new Foo)

^ this.constructor 将是 Foo,并且 StyleableComponent 类需要查看 Foo.style .

那么我该怎么做呢?我是否需要以某种方式使用额外的模板类型参数?

最佳答案

静态属性与实例属性继承

如果你想从子类中读取静态属性,你可以通过3种方式来实现。更多详细信息,你可以参见测试部分。

  • 因为Object.getPrototypeOf(..)的返回类型是any,所以可以直接访问style,例如:

    someMethod() {        
      let style = Object.getPrototypeOf(this).constructor.style;          
    }
    
  • 因为this.constructor的返回类型是Function,所以必须首先将其分配给any变量,例如:

    someMethod() {        
      let cotr:any=this.constructor;
      let style = cotr.style;          
    }
    
  • 因为Function是一个接口(interface),您可以在 typescript 中扩展它,例如:

    declare global{
      interface Function{
        style:any;
      }
    }
    
    someMethod() {        
      return this.constructor.style;         
    }
    

你也可以用实例属性替换静态属性来实现。如果你想读取子类的 style 属性,你必须在构造函数中定义该属性,然后子类可以选择通过传递定义其样式父类(super class)的 style 或根本不使用。例如:

constructor(protected style:any="default"){
}

有趣的是,除了 style 属性之外,子类的行为都是相同的。在设计 View 中,如果使用静态样式属性,则必须定义另一个子类来实现它,这往往会导致许多子类具有不同的样式。但是当使用实例属性 style 时,您可以通过传递 style 来实现,并且仅针对不同的 style 可选。示例:

let bar=new Bar();//use parent's style
let baz=new Bar(null,null,"baz");//use it owned style

你也可以通过在子类的构造函数中传递style来拒绝别人传递自己的样式,例如:

constructor(){
  super("style");
}

测试

import * as React from 'react';
declare global {
    interface Function {
        style: any
    }
}
describe('static inheritance', () => {

    class StyleableComponent<P, S> extends React.Component<P, S> {
        protected classes: any;
        static style: any;

        constructor(props?: P, context?: any, public style: any = "default") {
            super(props, context);
        }

        someMethod() {
            //dangerous if subclass not define static style property
            //todo:the 1st approach
            // let style = Object.getPrototypeOf(this).constructor.style;
            // return style;
            //todo:the 2nd approach
            // let cotr: any = this.constructor;
            // return cotr.style;
            //todo:the 3nd approach,you must declare style in Function interface
            return this.constructor.style;
        }
    }


    class Foo extends StyleableComponent<any, any> {
        static style = "foo";

        constructor(props?: any, context?: any) {
            super(props, context, Foo.style);
        }
    }

    class Bar extends StyleableComponent<any, any> {
    }

    test('access style from subclass', function () {
        let foo = new Foo();

        expect(foo.someMethod()).toBe(Foo.style);
    });


    test('return undefined if subclass not define style', function () {
        let bar = new Bar();

        expect(bar.someMethod()).toBeUndefined();
    });

    test('replace static style with instance property', function () {
        let foo = new Foo();
        let bar = new Bar();
        let baz = new Bar(null, null, "baz");

        expect(foo.style).toBe("foo");
        expect(bar.style).toBe("default");
        expect(baz.style).toBe("baz");
    });
});

关于javascript - 如何在基类代码内引用 `this.constructor` 上的静态属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42869737/

相关文章:

javascript - 数组的嵌套类,想要获取外部数组的索引

javascript - 按钮点击没有正确调用我的 Angular Directive(指令)

javascript - React.js 和 webpack - 为什么它不允许 var、let、const?

java - 在java中预定义泛型

Java 泛型和向上转型

typescript - 如何在 typescript 中输入生成器函数

javascript - 在 Javascript 中播放声音

c# - 你能从 C# 中的泛型中获取类型特定的行为吗?

Angular - 等到我收到数据后再加载模板

javascript - 使用 Array.map (TypeScript) 返回通用数组