扩展 Partial 接口的 Typescript 类

Twi*_*ron 7 typescript

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

我发现这篇文章指出了使用的方向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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

type AnimalDog = Dog & Animal;

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

Run Code Online (Sandbox Code Playgroud)

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

有没有办法告诉打字稿该类实现了接口,而无需显式声明每个接口属性?

Tit*_*mir 8

问题是Partial<T>只允许你实现成员不会要求你这样做,如果你不实现成员,它就不会出现在类中。

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

interface Animal {
    name: string;
}

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

var spot = new Dog();

spot.name = "Spot"; // ok now
Run Code Online (Sandbox Code Playgroud)

您还可以强制转换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"; 
Run Code Online (Sandbox Code Playgroud)