【发布时间】:2019-01-03 20:05:53
【问题描述】:
我正在处理一个Typescript 项目,虽然代码编译得很好,并且在所有概念的理论领域中代码应该可以工作,但它在运行时不起作用。
我已经缩小了问题的范围,即
TypeScript在编译后被转换为JavaScript。这意味着没有定义的类和变量类型(管道类型也称为解释语言)。
现在我需要帮助的地方是让它工作。下面是类结构:
基类
当我从 API 获得响应时,我将其转换为基类类型
class BaseCollectionTypeResponseModel<TObject>{
protected responseData: Array<TObject>;
protected pagination: PaginationResponseModel;
}
PaginationResponseModel 定义如下:
class PaginationResponseModel {
protected totalItems: number;
protected totalPages: number;
protected currentPage: number;
protected itemCount: number;
}
现在我定义了一个interface,它有一个函数ConvertViaAdapter(),如下所示:
interface IConvertable{
ConvertViaAdapter();
}
实现该接口的示例类如下:
class PlatformResponseModel implements IConvertable{
protected status: number;
protected name: string;
protected platformid: string;
protected tags: string[];
protected type: string;
protected version: string;
protected description: string;
ConvertViaAdapter(): PlatformModel {
return Object.assign(new PlatformModel(), this)
}
}
现在我正在创建利用基类功能提供应用程序特定功能的子类。
子类:
例如,分页子类如下所示: 类 PaginationModel 扩展 APIResponses.PaginationResponseModel{
get TotalItems(): number{
return this.totalItems
}
get TotalPages(): number{
return this.totalPages
}
get CurrentPage(): number{
return this.currentPage
}
get ItemCount(): number{
return this.itemCount
}
}
现在事情变得棘手了:
我已经扩展了PlatformResponseModel,如下所示:
class PlatformFunctionalModel extends PlatformResponseModel{
get Name(): string{
return this.name
}
get IsActive(): boolean{
if (this.type == 0)
return True;
return False;
}
}
我还使用下面的泛型扩展了 BaseCollectionTypeModel:
class CollectionTypeBaseModel<TObject extends YObject, YObject extends IConvertable> extends BaseCollectionTypeResponseModel<YObject>{
private _responseData: Array<TObject> = []
get ResponseData(): Array<TObject>{
if (this._responseData == null || this._responseData.length < 1){
this.responseData.forEach((data)=>{
this._responseData.push(data.ConvertViaAdapter());
});
}
return this.responseData;
}
set ResponseData(data: Array<TObject>){
this.responseData = data
this._responseData = data
}
get Pagination(): PaginationModel{
return Object.assign(new PaginationModel(), this.pagination)
}
}
问题出在上面类中的代码行this.responseData.forEach(),我得到错误:
对象类型没有
ConvertViaAdapter()的方法。
现在它应该可以工作了,因为当TObject 扩展IConvertable 接口时,TObject 类型的列表项将定义并实现函数,否则代码将无法编译。我需要帮助。
JSON 示例
{"responseData":[{"status":2,"name":"HelloSample","platformid":"A1B2C3","tags":["hello","sample"],"type":"delta","version":"v1.0","description":"Just a sample"}],"pagination":{"totalItems":10,"totalPages":5,"currentPage":1,"itemCount":2}}
起始码:
var objectData = JSON.parse(jsonData);
var myCastedData = Object.assign(new CollectionTypeBaseModel<PlatformFunctionalModel, PlatformResponseModel>(), objectData)
【问题讨论】:
-
我强烈建议您将数据和操作分开。 Classes + JSON 会导致悲伤,有时会导致精神错乱,而你却一无所获。此外,您似乎对鸭子打字与解释与编译感到困惑,而这些都与您的问题无关。您的问题是使用类作为类型注释并假设会自动应用转换。即使在具有完全具体化类型系统的语言(例如 C#)中,也需要反射序列化系统来处理 JSON、XML 和其他文本数据
-
@AluanHaddad 是的,我知道
C#处理序列化和反序列化的方式。我正在研究如何在 TypeScipt 中使用DataContract JSON Serialization and Deserialization。遇到了一个叫做TypedJSON的东西。问题是这段代码。它在 C# 中效果很好我已经测试了代码的流程,然后再把问题放在这里。 -
不要走那条路。你会后悔的,或者充其量,你不会知道自己有多悲惨:p。这种方法不适用于 JavaScript 或 TypeScript。如果您认为 TypeScript 编译为纯 JavaScript 是一个弱点,那么您将永远不会很好地使用它。 TypeScript 仅用于工具,它非常适合。
-
@AluanHaddad 哦。有没有更好的方法可以告诉我我可以塑造代码,我有一个服务库,可以进行 API 调用,然后需要将响应从 JSON 对象转换为
BaseCollectionTypeResponseModel<PlatformResponseModel>,然后再转换为CollectionTypeBaseModel<PlatformFunctionalModel, PlatformResponseModel> -
我建议你放弃这种方法。使用
interfaces 声明 API 响应的形状,并使用外部函数或服务类对它们进行操作,这些函数或服务类采用普通对象和数组并返回普通对象和数组。使用非类类型键入这些方法并使用静态鸭子类型。
标签: typescript generics interface casting