2

我不知道如何正确描述这一点,所以让我举个例子。我有一个库,它返回一个用作构造函数的函数:

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;
}

基本上我想以某种方式定义声明实际用户的代码在哪里。根据我对环境声明的了解,它们在“其他地方”被指定。我无法弄清楚这个“其他地方”实际上在哪里。我检查了一个打字稿示例,但我没有看到 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();

用户对象包含从猫鼬给你的任何东西(我已经映射到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 编译器崩溃并且不会更新了我使用参考的文件。

4

1 回答 1

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 文件中。

让我知道我是否正确理解了您的问题。

在进一步信息后编辑

好的。我对猫鼬不熟悉,但让我看看我在这里是否理解正确(在快速浏览http://mongoosejs.com/docs/index.html之后)

  • 您有一个由属性包定义的模式,其中键是名称,值是类型,即 { name: String, age: Number}。
  • 您将它传递给 mongoose.Schema,它会返回一个新文档“模式”。
  • 您将其传递给 mongoose.model(连同名称)并取回与此模式匹配的新“文档”的构造函数
  • 然后,您可以通过所概述模式的构造函数“新建”文档。
  • 返回的对象还具有常见的 mongoose 文档方法,例如用于数据存储操作的“保存”和“查找”。

这很有趣,因为 Schema 归结为结构类型大纲,类似于 TypeScript 中的接口,以几乎类似于 JSON 的语法指定,传递原始构造函数来指定类型(数字、字符串、日期等)。但是,由于 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*/ });
于 2013-03-14T01:20:59.517 回答