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

基本的に、実際のユーザーを宣言するコードがどこにあるかを何らかの形で定義したいと考えています。アンビエント宣言について私が理解していることから、それらは「他の場所」で指定されています。この「他の場所」が実際にどこにあるのかわかりません。タイプスクリプトの例の1つを確認しましたが、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();

これを行うと、次の例外で typescript コンパイラがクラッシュし、私は何か非常に奇抜で、おそらく正しくないことをしていると信じるようになります。

\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をざっと見てから)

  • キーが名前で、値がタイプ、つまり{名前:文字列、年齢:数値}であるプロパティバッグによって定義されたスキーマがあります。
  • これをmongoose.Schemaに渡すと、新しいドキュメント「schema」が返されます。
  • これを(名前とともに)mongoose.modelに渡し、このスキーマに一致する新しい「ドキュメント」のコンストラクターを取得します。
  • 次に、概説したスキーマのこのコンストラクターを介してドキュメントを「新規作成」できます。
  • 返されるオブジェクトには、データストア操作用の「save」や「find」などの一般的なマングースドキュメントメソッドもあります。

スキーマは、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 に答える