我有一个TypeScript文件,其中包含从服务器实体模型自动生成的实体信息。对于每种实体类型,该文件包含TypeScript接口和元数据。
一个实体的简化示例:
// Auto-generated
interface Report {
id: number;
title: string;
}
interface ReportEntityType extends EntityType<Report> {
properties: {
id: Property<number>;
title: Property<string>;
}
}
var entityTypes = {
Report: <ReportEntityType>{
properties: {
id: {
dataType: "number"
},
title: {
dataType: "string",
required: true,
displayName: "Title"
}
}
}
};
为了完整性,这里是引用的接口(也简化):
interface EntityType<T> {
properties: any;
}
interface Property<T> {
dataType: string;
required?: boolean;
displayName?: string;
}
虽然在项目中,Report
接口在编译时用于类型检查和智能感知,并且entityTypes.Report
元数据对象在编译和运行时用于各种目的。例如,displayName
用于呈现属性的标签,required
用于验证。
如何让TypeScript从类型Report
推断类型ReportEntityType
?
示例:
class Validator<TEntityType> {
constructor(entityType: EntityType<TEntityType>) { }
validate(obj: TEntityType) { }
}
var validator = new Validator(entityTypes.Report);
目前,TypeScript会推断validator
是Validator<{}>
,但我希望它推断它是Validator<Report>
。
根据TypeScript团队here和here的评论,问题是我的EntityType<T>
界面本身不使用T
参数:
我认为未使用的泛型类型参数通常是错误
不要定义不使用类型参数类型
的泛型类型
足够公平。有趣的是,我所要做的就是向dummy?: T;
添加EntityType<T>
属性并且它有效。我想避免这种破解,而是以惯用的TypeScript方式实现这一点。我该怎么办?
答案 0 :(得分:0)
简化示例:
interface Report{}
interface EntityType<T> {
properties: any; // Change to T and it works
}
interface ReportEntity extends EntityType<Report>{}
var rep1:EntityType<Report>;
var rep2:ReportEntity;
class Validator<TEntityType> {
constructor(entityType: EntityType<TEntityType>) { }
}
var val1 = new Validator(rep1); // okay
var val2 = new Validator(rep2); // Not okay
此处的问题是,如果您在T
中没有使用EntityType
,则rep2
实际上是EntityType<{}>
。因此除了使用T
||之外,没有其他好的解决方案不使用扩展接口(参见rep1
)。