Typescript类扩展Partial接口

时间:2019-03-04 15:26:40

标签: typescript

我想创建一个具有接口的所有属性的类,但实际上并不声明这些属性本身。接口属性在构建过程中附加,并且在运行时存在。

我发现this post向我指出了使用Partial<T>的方向...但这似乎行不通。以下代码不会产生编译错误。

interface Animal {
    name: string;
}

interface HasConstructor {
    constructor: any;
}
//Do this to supress this error: "Type 'Dog' has no properties in common with type 'Partial<Animal>"
type OptionalAnimal = Partial<Animal> & HasConstructor;

class Dog implements OptionalAnimal {
    public constructor() {

    }
    public breed: string;
}

但是,name属性在Dog实例上不可用。

var spot = new Dog();
spot.name = "Spot"; //ERROR: Property 'name' does not exist on type 'Dog'

我可以通过创建另一个类型并像这样引用它来解决此问题:

type AnimalDog = Dog & Animal;

var spot: Animal = new Dog() as any;
spot.name = "Spot";

但是,我无法构造AnimalDog的新实例,并且必须强制转换为any才能使类型对齐,因此我只能同时使用AnimalDog根据情况,在我的代码中为 Dog。引用动物类型时,这还会在Dog内部产生编译错误。

是否有一种方法可以告诉Typescript该类实现了接口,而没有显式声明每个接口属性?

1 个答案:

答案 0 :(得分:1)

问题在于Partial<T>仅允许您实现成员,而不要求您这样做;如果您不实现成员,则它将不在类中。

您可以创建一个返回一个类的函数,该类将实现该接口。返回的类实际上不必声明任何字段,因此它们都将为undefined,但这应该没问题,因为这些字段无论如何都是可选的。

interface Animal {
    name: string;
}

type OptionalAnimal = Partial<Animal>;
function autoImplment<T>(): new () => T {
    return class { } as any;
}
class Dog extends autoImplment<OptionalAnimal>() {
    public constructor() {
        super();
    }
    public breed: string;
}

var spot = new Dog();

spot.name = "Spot"; // ok now

您还可以强制转换Dog类以指定返回的实例具有Animal的成员,但是这些新成员将无法从该类内部进行访问:

interface Animal {
    name: string;
}

class _Dog {
    public constructor() {

    }
    public breed: string;
}

const Dog = _Dog as { new(): _Dog & Partial<Animal> } & typeof _Dog
type Dog = InstanceType<typeof Dog>

var spot = new Dog();

spot.name = "Spot";