簡體   English   中英

打字稿:這是多病的,重載簽名與函數實現不兼容

[英]Typescript: polymorhpic this, overload signature is not compatible with function implementation

有人可以解釋為什么這不起作用:

abstract class Model {
    static deserialize<T extends Model>(this: ( new() => T ), object: any): T;
    static deserialize<T extends Model>(ctor: ( new() => T ), object: any): T {
        return new ctor();
    }

    static deserializeArray<T extends Model>(this: ( new() => T ), ...objects: any[]): T[];
    static deserializeArray<T extends Model>(ctor: ( new() => T ), ...objects: any[]): T[] {
        return objects.map(object => Model.deserialize(ctor, object));
    }
}

class MyModel extends Model { }

這將允許:

let myModel = MyModel.deserialize({});
let myModels = MyModel.deserializeArray({}, {}, {});

要么

let myModel = Model.deserialize(MyModel, {});
let myModels = Model.deserializeArray(MyModel, {}, {}, {});

打字稿2.5.2抱怨“過載簽名與函數實現不兼容”。

為什么都需要兩種形式?

考慮一個返回序列化(json)模型的REST API:

class MyModelController {
    get(id: number) {
        let myModel = ... some db/service call ...
        return myModel.serialize();
    }
}

然后是通用服務(角度)來請求模型:

@Injectable()
abstract class HttpService {
    constructor(private http: Http) { }

    errorHandler(response) {
        ...
    }

    get<T extends Model>(ModelType: ( new() => T ), endpoint: string): Observable<T> {
        return this.http.get(endpoint)
            // we can't call ModelType.deserialize() here...
            .map(response => Model.deserialize(ModelType, response.json()))
            .catch(response => this.errorHandler(response));
    }
}

@Injectable()
class MyModelService extends HttpService {
    get(id: number) {
       return super.get(MyModel, `/api/models/${id}`);
    }
}

abstract class Model {
    static deserialize<T extends Model>(this: ( new() => T), object: {}): T;
    static deserialize<T extends Model>(this: Function & { prototype: Model }, ctor: ( new() => T ), object: {});
    static deserialize<T extends Model>(this: ( new() => T), first: ( new() => T ) | {}, second?: any) {
        return typeof first === "function" ? new first() : new this(); 
    }

    static deserializeArray<T extends Model>(this: ( new() => T), ...objects: {}[]): T[];
    static deserializeArray<T extends Model>(this: Function & { prototype: Model }, ctor: ( new() => T ), ...objects: {}[]): T[];
    static deserializeArray<T extends Model>(this: ( new() => T), first: ( new() => T ) | {}[], second?: {}[]): T[] {
        const ctor = typeof first === "function" ? first : this;
        const objects = typeof first === "function" ? second : first;
        return objects.map(object => Model.deserialize(ctor, object));
    }
}

這樣既可以保留兩種形式,又可以保留abstract

我認為沒有必要同時使用以下兩種方法:

let myModel1 = MyModel.deserialize({});
let myModel2 = Model.deserialize(MyModel, {});

第一種形式已足夠且更具可讀性,然后代碼如下所示:

type ModelCtor<T extends Model> = {
    new(): T;
    deserialize<T extends Model>(object: any): T;
    deserializeArray<T extends Model>(...objects: any[]): T[];
};

abstract class Model {
    static deserialize<T extends Model>(this: ModelCtor<T>, object: any): T {
        return new this();
    }

    static deserializeArray<T extends Model>(this: ModelCtor<T>, ...objects: any[]): T[] {
        return objects.map(object => this.deserialize(object));
    }
}

class MyModel extends Model { }

let myModel = MyModel.deserialize({});
let myModels = MyModel.deserializeArray({}, {}, {});

操場上的代碼

但是,如果出於某種原因,我確實想同時擁有這兩種形式,則可以執行以下操作:

type ModelCtor<T extends Model> = {
    new(): T;
    deserialize<T extends Model>(object: any): T;
    deserialize<T extends Model>(ctor: ModelCtor<T>, object: any): T;

    deserializeArray<T extends Model>(...objects: any[]): T[];
    deserializeArray<T extends Model>(ctor: ModelCtor<T>, ...objects: any[]): T[];
};

class Model {
    static deserialize<T extends Model>(this: ModelCtor<T>, object: any): T;
    static deserialize<T extends Model, S extends Model>(this: ModelCtor<T>, ctor: ModelCtor<S>, object: any): S;
    static deserialize<T extends Model, S extends Model>(this: ModelCtor<T>, first: ModelCtor<S> | any, second?: any): S {
        return second === undefined ? new this() : new first();
    }

    static deserializeArray<T extends Model>(this: ModelCtor<T>, ...objects: any[]): T[];
    static deserializeArray<T extends Model, S extends Model>(this: ModelCtor<T>, ctor: ModelCtor<S>, ...objects: any[]): S[];
    static deserializeArray<T extends Model, S extends Model>(this: ModelCtor<T>, ...objects: any[]): S[] {
        const ctor: ModelCtor<S> = typeof objects[0] === "function" ? objects[0] : this as any;
        return objects.map(object => ctor.deserialize(ctor, object));
    }
}

class MyModel extends Model { }

let myModel1 = MyModel.deserialize({});
let myModels1 = MyModel.deserializeArray({}, {}, {});

let myModel2 = Model.deserialize(MyModel, {});
let myModels2 = Model.deserializeArray(MyModel, {}, {}, {});

操場上的代碼

該代碼更編譯(我認為沒有充分的理由)。
另外,我必須從Model刪除abstract部分,否則會出現此錯誤:

類型“ typeof Model”的“ this”上下文不能分配給類型“ ModelCtor”的方法“ this”。
無法將抽象構造函數類型分配給非抽象構造函數類型。

對於這兩行:

let myModel2 = Model.deserialize(MyModel, {});
let myModels2 = Model.deserializeArray(MyModel, {}, {}, {});

也許您可以多進行一些操作,並在不刪除abstract情況下解決這些錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM