【发布时间】:2017-09-16 02:08:55
【问题描述】:
谁能解释为什么这不起作用:
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, {}, {}, {});
Typescript 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。
【问题讨论】:
-
第二种形式的意义何在?如果你可以做
MyModel.deserialize({});为什么你需要做Model.deserialize(MyModel, {});? -
是的,但如果你有
ModelType,那么你可以简单地使用ModelType. deserialize(...)。它肯定扩展了Model,因此它引用了静态deserialize函数。 -
我无法致电
ModelType.deserialize()。如果我重构以包含您的ModelCtor<T>类型(具有反序列化签名),则MyModel不可分配给ModelCtor<T>。
标签: typescript