替代从未消耗的通用参数推断类型

时间:2014-12-09 00:57:06

标签: typescript

我有一个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会推断validatorValidator<{}>,但我希望它推断它是Validator<Report>

根据TypeScript团队herehere的评论,问题是我的EntityType<T>界面本身不使用T参数:

  

我认为未使用的泛型类型参数通常是错误

     

不要定义不使用类型参数类型

的泛型类型

足够公平。有趣的是,我所要做的就是向dummy?: T;添加EntityType<T>属性并且它有效。我想避免这种破解,而是以惯用的TypeScript方式实现这一点。我该怎么办?

1 个答案:

答案 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)。