从库中创建新类

时间:2013-03-13 23:58:31

标签: mongoose typescript

我不知道如何恰当地描述这个,所以让我想出一个例子。我有一个库,它返回一个用作构造函数的函数:

var userTemplate = lib.User;
var user = new userTemplate();

我想强调这个userTemplate作为一个类,因为我知道它将具有哪些属性。我还希望能够在应用程序的其他部分执行var user = new userTemplate()之类的操作,并使user对象具有某种已知类型。

我觉得我需要在这里使用环境类声明,但我不确定如何将环境声明分配给实际生成器的引用?

例如,我想要这样的事情:

export class Storage{
    init(){

        // somehow define that when you 
        // new a User to call this function

        User = lib.User; 
     }
}

declare class User{
   public name:string;
}

基本上我想以某种方式定义声明实际用户的代码在哪里。根据我对环境声明的理解,它们被指定为“其他地方”。我无法弄清楚这个“其他地方”到底在哪里。我检查了typescript examples之一,但是我没有看到mongodb环境声明是如何映射到实际实现的。

我觉得我在这里错过了一块拼图。

编辑(具体细节)

让我具体说明一下:

我正在尝试使用强类型猫鼬。想象一下,我有一个Schema类:

export class Schema{
    public UserData:User;

    constructor(){
        var mongoose:IMongooseBase = require("mongoose");
        var mongooseSchema = <MongooseSchema>mongoose.Schema;


        var user = new mongooseSchema({
            name: String
        });

        this.UserData = mongoose.model("User", user);
    }
}

export declare class User extends MongooseBase{
    constructor(item:any);
    public _id: string;
    public name: string;
}


declare class MongooseBase {
    findOne(item:any, callback:ICallback) : void;
    find(id:string, callback?:ICallback) : IChainable;
    save(item: IEmptyCallback) : void;
    remove(item:any, callback:IErrorCallback) : void;
    push(item:MongooseBase):void;
}

interface IMongooseSchema{
    ObjectId:String;
}

declare class MongooseSchema implements IMongooseSchema{
    constructor(item:any);
    public ObjectId:String;
}
interface IMongooseBase{
    model(name:String, ref:any):any;
    Schema():any;
}

Mongoose的模型函数为我提供了一个用作构造函数的函数。使用此对象创建任何新模型类型将在MongooseBase中定义属性(例如find,findOne等)。我还希望此用户将用户属性定义为环境类User(名称)中定义的模式的一部分。

所以,例如,在javascript中这类似于

var userProxy = mongoose.Schema("User", user);

var userData = new userProxy();

用户对象包含任何mongoose为您提供的继承属性(我已将其映射到MongooseBase定义)。它还为您提供了作为初始模式创建的一部分传入的属性(当我定义user时)。

我希望能够强烈输入此代理,例如

var user:UserData = new schema.UserData();

如果我这样做,那么打字稿编译器会因以下异常而崩溃,导致我相信我正在做一些疯狂的事情而且可能不对:

\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:24488
                throw err;
                      ^
TypeError: Cannot read property 'construct' of null
    at TypeFlow.typeCheckNew (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:20675:27)
    at CallExpression.typeCheck (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:1275:33)
    at TypeFlow.typeCheck (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:18505:28)
    at TypeChecker.typeCheckWithContextualType (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:15909:27)
    at TypeFlow.typeCheckBoundDecl (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:18647:38)
    at VarDecl.BoundDecl.typeCheck (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:1631:29)
    at ASTList.typeCheck (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:1016:55)
    at TypeFlow.typeCheck (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:18505:28)
    at TypeFlow.typeCheckFunction (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:19815:22)
    at FuncDecl.typeCheck (\AppData\Roaming\npm\node_modules\typescript\bin\tsc.js:1783:29)

编辑2

所以我设置它的方式我没有在webstorm中得到任何错误,并且生成的其他文件的代码确实正常工作(它匹配我自己编写的javascript),但是typescript编译器崩溃了不会更新我使用引用的文件。

1 个答案:

答案 0 :(得分:3)

看起来你想在你的库中声明你的库和构造函数(建模为下面的类)。这是你在找什么?

declare module lib {
  export class User {
    name: string;
    age: number;
    getChildren(): User[];
  }
}

var userTemplate = lib.User;
var user = new userTemplate();
user.name = "dave";

通常,您的库声明将在您引用的.d.ts文件中。

如果我理解你的问题,请告诉我。

进一步信息后编辑

行。我对Mongoose不熟悉,但让我看看我是否正确理解(快速查看http://mongoosejs.com/docs/index.html后)

  • 您有一个由属性包定义的模式,其中键是一个名称,值是一个类型,即{name:String,age:Number}。
  • 您将此传递给mongoose.Schema,并返回一个新文档'schema'。
  • 您将此传递给mongoose.model(以及名称)并获取与此架构匹配的新“文档”的构造函数
  • 然后,您可以通过此纲要的构造函数“新建”文档。
  • 返回的对象也有常见的mongoose文档方法,如“save”&amp; “查找”数据存储区操作。

这很有趣,因为Schema归结为结构类型大纲,类似于TypeScript中的接口,以类似JSON的语法指定,传递主要构造函数来指定类型(Number,String,Date等... )。但是,由于TypeScript类型纯粹是在发出的JavaScript中不存在的注释,因此您无法重用它们(并且它们具有不同的类型,如ObjectID)。

一旦我们使用该语言获得泛型,我们就会有更聪明的方法来执行此操作并通过查找,保存等方式流式传输文档类型......但下面是我认为当前键入此内容的最简单方法。这与你追求的更加一致吗?

// Let's type it as any for now
declare var mongoose: any;

// Base interface that any 'document' will have
interface mongooseBase {
    find: (callback: { (err: any, items: any[]): void; }) => void;
    save: (hanlder: { (err: any): void; }) => void;
}

// This is the structure our 'person' document will have
interface person extends mongooseBase {
    name: string;
    age: number;
    children: { name: string; dependent: bool; }[];
};

// Need to provide the same structure in 'mongoose' style format to define.
var personSchema = mongoose.Schema({ name: String, age: Number, children: [{ name: String, dependent: Boolean }] });

// Get back a constructor function.  We assert that the type returned is a 'newable' Function (a constructor), and will return a 'person' type when called
var Person = <{ new (): person; }>mongoose.model('Person', personSchema);

// Let's create one
var p1 = new Person();

// Let's set a property
p1.name = "Dave";

// Let's save Dave
p1.save(function (err) { /*TODO*/ });