忽略具有泛型类型的类的属性

时间:2019-12-26 21:23:20

标签: typescript class typescript-generics

我正在研究Typescript entities library(编码/解码JSON <=>类)。

我正在尝试正确进行类型检查,并在我的Entity类上成功实现了它,但是在我的EntityBuilder类上却无法正确实现它。

原因是Entity适用于类实例,而EntityBuilder适用于类。

这是一个代码示例(Typescript playground):

class A {
    x: number;
    z: number;
}

export class EntityBuilder {
    /**
     * Build an entity object from source data.
     */
    public static buildOne<T extends any>(buildClass: T, sourceData: Omit<T, 'fromJson'|'toJson'>): T {
        this.checkClassValidity(buildClass);

        const entity: any = new buildClass();

        if (buildClass.constructor === Array.constructor) console.log(sourceData)

        // we ensure that `fromJson` is available as this
        // could simply be annotated with `@Type(Object)`
        if (typeof entity.fromJson === 'function') {
          entity.fromJson(sourceData);
          return entity;
        } else {
          return sourceData as T // don't mind me
        }
    }

    /**
     * Build multiple entities from an array of source data.
     */
    public static buildMany<T>(buildClass: T, sourceData: Omit<T, 'fromJson'|'toJson'>[]): T[] {
        this.checkClassValidity(buildClass);

        return sourceData.map(entityData => this.buildOne<T>(buildClass, entityData));
    }

    /**
     * Check if a valid class was passed through.
     */
    private static checkClassValidity(buildClass: any) {
        if (typeof buildClass !== 'function') {
            throw new Error('Class could not be found');
        }
    }
}

EntityBuilder.buildOne(A, {})

最后一行返回以下错误:

Argument of type '{}' is not assignable to parameter of type 'Pick<typeof A, "prototype">'.
  Property 'prototype' is missing in type '{}' but required in type 'Pick<typeof A, "prototype">'.

虽然我希望它能告诉我第二个参数缺少xz属性。

我省略了fromJsontoJson,因为这些是我Entity class中的方法,应作为class A的父类使用(简单代码中不包含这些方法)例如)。

我真的可以帮上忙,整个下午我都在忙着,我想我已经检查了几乎所有的SO和Github线程。

谢谢。

1 个答案:

答案 0 :(得分:1)

您需要区分拳头参数(创建T的实例)和第二个参数(T的类型)。

ppublic static buildOne<T>(buildClass: new () => T, sourceData: Omit<T, 'fromJson'|'toJson'>): T

这告诉打字稿您要使用buildClass运算符调用new并返回T的实例,因为buildClass本身不是{{1的实例}}。

T

您现在应该得到一个错误,即您所传递的空对象丢失了EntityBuilder.buildOne<A>(A, {}) x,就像您期望的那样。

作为旁注,我不确定将z键入为sourceData的实例是否合理,考虑到重点是创建T的实例。您还可以让T扩展某些内容,例如使用T方法而不是fromJson