如何使用类型脚本与Ampersand.js这样的库来解析配置来构建原型

时间:2014-08-10 09:35:47

标签: typescript ampersand.js

我的问题是如何使用像AmpersandJS这样的库或其他库解析配置来构建你的(类)对象(我不确定这个模式是否有名称)和Typescript。例如,Ampersand.JS使用函数(.extend)根据您的配置构建原型:

    // This object contains the configuration that Ampersand uses to build my model.
    var config = {
        props: {
            firstName: 'string',
            lastName: 'string'
        }
    };

    // Create a Person model with getters, setters, validation etc. 
    var Person = AmpersandModel.extend(config);

    // A basic usage to create an instance of a Person object
    var myPerson = new Person({firstName:"John", lastName:"Doe"});
    myPerson.firstName = "NewJohn"; // runs the first name setter build by ampersand

我正在努力如何在Typescript上使用上面的例子。使用Backbone等其他库,您可以使用常规/简单的Typescript方法:

    MyModel extends Backbone.Model{}

然而,对于像Ampersand.JS这样的库,我无法使用:

    Person extends AmpersandModel{}

因为这将永远不会执行AmpersandModel的自定义extend()代码,该代码根据传递给extend()函数的配置构建原型。

我不确定其他哪些库会遇到同样的问题,以及他们使用什么解决方案。使用Ampersand模式的库的任何示例都可能有所帮助。

1 个答案:

答案 0 :(得分:0)

这是我想出的 - 首先我删除了Ampersand.js模块定义。我从未使用过Ampersand,所以只是关闭他们的文档:

declare module ampersand {
    interface AmpersandState {
        // todo...
    }

    interface AmpersandCollection {
        // todo...
    }

    interface ModelExtendOptions {
        parse?: boolean;
        parent?: AmpersandState;
        collection?: AmpersandCollection;
    }

    interface ModelSaveOptions {
        patch?: boolean;
    }

    interface AmpersandModel<TProps> {
        save: (attrs?: TProps, options?: ModelSaveOptions) => void;
        // todo:  fetch, destroy, sync, etc...
    }

    interface AmpersandModelConstructor<TProps, TModel extends AmpersandModel<any>> {
         new (attrs: TProps, options?: ModelExtendOptions): TModel;
    }   

    interface ExtendOptions {
        props?: {};
        session?: {};
        derived?: {};
    }   

    interface AmpersandModelStatic {
        extend: <TProps, TModel extends AmpersandModel<any>>(options: ExtendOptions) => AmpersandModelConstructor<TProps, TModel>;
    }
} 

declare var AmpersandModel: ampersand.AmpersandModelStatic;

以下是如何使用上述&符号模块定义来定义自己的接口等。

由于Typescript泛型和继承的限制,您需要为每种模型类型创建两个接口:一个用于它的属性,另一个用于组合属性和&符号基础模型:

// interface for person properties...
interface PersonProps {
    firstName: string;
    lastName: string;
}

// interface to tie everything together...
interface PersonModel extends PersonProps, ampersand.AmpersandModel<PersonProps> {
}

// use AmpersandModel's extend method...
var Person = AmpersandModel.extend<PersonProps, PersonModel>({ props: { firstName: 'string', lastName: 'string' } });

// at this point you now have full intellisense/type checking for the constructor and properties.
var me = new Person({ firstName: 'Jeremy', lastName: 'Danyow' });
me.firstName = 'Ron';  // yes!
me.eyeColor = 'Brown'; // compile error!

<强> [Here's a link to run the code in the typescript playground]