从Javascript转换为Typescript、Knockout和DevExtreme控件

从Javascript转换为Typescript、Knockout和DevExtreme控件,typescript,knockout.js,devextreme,Typescript,Knockout.js,Devextreme,我在从Javascript转换到Typescript时遇到了一些问题,尤其是在创建devextreme控件时 过去,我会在我的viewmodel中为devextreme控件创建一个对象,如下所示: self.myButton = { text: 'Click Me', disabled: ko.purecomputed(function(){ return self.myobservable().length>0;}); } 这很好用,我试过用打字机 myButton: DevE

我在从Javascript转换到Typescript时遇到了一些问题,尤其是在创建devextreme控件时

过去,我会在我的viewmodel中为devextreme控件创建一个对象,如下所示:

self.myButton = {
  text: 'Click Me',
  disabled: ko.purecomputed(function(){ return self.myobservable().length>0;});
}
这很好用,我试过用打字机

myButton: DevExpress.ui.dxButtonOptions;
然后在构造函数中

....
self.myButton = {
  text: 'Click Me',
  disabled: ko.purecomputed(function(){ return self.myobservable().length>0;});
}
...
这给了我一个错误类型KnockoutComputed不能分配给boolean类型,这很公平,我得到了这个

但问题是,应该如何做到这一点

我可以用这个:

myButton: any; 
在按钮选项的声明中,但我认为这有点违背了使用typescript的目的

这是可行的,使用typescript的原因之一就是要使用像webpack之类的东西,所以这不是完全的损失,我只是想知道如何正确地做到这一点


提前感谢。

我已经检查了使用和解决您的问题的可能性。然而,我认为最干净的方法是简单地使用任何类型的小部件选项

两个示例的模板相同:

<div data-bind="dxButton: buttonOptions"></div>

一个想法是:您可以尝试使用
keyof
并扩展
DevExpress
接口,将
KnockoutComputed&T
作为值。作为一个选项,您可以将其用于属性。在这种情况下,属性将具有简单的类型,并可用于DevExtreme的选项。@unional您能给我一些关于如何在devexpress界面上使用keyof的示例吗?我对typescript不太熟悉,所以不知道从何处开始?@mykhailo.romaniuk谢谢您提供的链接,我从未见过这个,但它看起来确实不错。但有一个问题是,如果我要这么做,我是否必须将我的pureCompute分解成一个单独的vm方法?@jasoncley我玩了一点,他们似乎无法解决您的问题。我也想过使用这个库,但是所有解决这个库问题的方法对我来说都是一种解决方法。我不得不说,我认为没有比使用任何控件选项更好的方法了
// importing thing from DevExtreme.
import "devextreme/ui/button";
import DevExpress from "devextreme/bundles/dx.all";

import * as ko from "knockout";
// importing knockout-es5 to include track and defineProperty functionality
import "knockout-es5";

// This small util will make creation of compute a bit more strong by using keyof
const createComputed = <T>(prototype: T, key: keyof T, computedFunc: Function): void => {
    ko.defineProperty(prototype, key, computedFunc);
}

class DevextremeTestViewModel {
    clickCounter: number = 0;
    buttonOptions: DevExpress.ui.dxButtonOptions;

    constructor() {
        this.buttonOptions = {
            text: "Start",
            onClick: this.increaseCounter
        };

        // start tracking clickCounter property (make it observable)
        ko.track(this, ["clickCounter"]);

        // assign to text property of widget options computed value
        createComputed(this.buttonOptions, "text", () => {
            return `Clicked ${this.clickCounter} times`;
        });
    }

    increaseCounter(): void {
        this.clickCounter++;
    }
}
import "devextreme/ui/button";
import DevExpress from "devextreme/bundles/dx.all";
// include required decorators
import { observable, computed } from "knockout-decorators";

// Magic function to copy getter from one property to another
const copyGetter = <T, TProp>(prototype: T, key: keyof T, propProto: TProp, propertyKey: keyof TProp) => {
    let getter = Object.getOwnPropertyDescriptor(propProto, propertyKey).get;
    Object.defineProperty(prototype, key, {
        get: getter
    });
}

class DevextremeTestViewModel {
    // Create observable
    @observable clickCounter: number = 0;
    // Create computed that based on observable
    @computed({ pure: true }) get buttonText(): string {
        return `Clicked ${this.clickCounter} times`;
    };
    buttonOptions: DevExpress.ui.dxButtonOptions;

    constructor() {
        this.buttonOptions = {
            text: this.buttonText,
            onClick: this.increaseCounter
        };

        // Need to copy getter from our computed to options property.
        copyGetter(this.buttonOptions, "text", this, "buttonText");
    }

    increaseCounter(): void {
        this.clickCounter++;
    }
}
import "devextreme/ui/button";
import DevExpress from "devextreme/bundles/dx.all";
import { observable, computed } from "knockout-decorators";
import * as ko from "knockout";

class DevextremeTestViewModel {
    // Create observable
    @observable clickCounter: number = 0;
    buttonOptions: any = {
        text: ko.pureComputed(()=> {
            return `Clicked ${this.clickCounter} times`;
        }),
        onClick: this.increaseCounter
    };

    increaseCounter(): void {
        this.clickCounter++;
    }
}