我尝试通过各种类型的输入来处理模型/集合模式,但是我陷入了困境。简而言之,模型和集合都具有serialize()
方法。在Collection上调用序列化方法将序列化所有Model。
这里是Typescript Playground that's I've been working on。
/**
* MODEL
*/
interface SerializedModel {
type: string;
}
interface ModelInterface {
serialize(): SerializedModel;
}
/**
* MODEL: Contact
*/
interface SerializedContact extends SerializedModel {
name: string;
}
class Contact implements ModelInterface {
public name: string;
public constructor(name: string) {
this.name = name;
}
public serialize(): SerializedContact {
return {
type: "Contact",
name: this.name,
};
}
}
/**
* COLLECTION
*/
interface SerializedCollection<M> {
count: number;
items: { serialize(): M };
}
interface CollectionInterface<I> {
count: number;
items: I;
serialize(): SerializedCollection<I>;
}
class Collection implements CollectionInterface<ModelInterface[]> {
public count: number;
public items: ModelInterface[];
public constructor(items: ModelInterface[], count: number) {
this.items = items;
this.count = count;
}
public serialize(): SerializedCollection<ModelInterface[]> {
return {
count: this.count,
items: this.items.map((item) => item.serialize()),
};
}
}
/**
* TESTING
*/
// This is where I'm stuck. I feel like I need to do something like this...
const contactCollection = new Collection<Contact>(
[new Contact("Bill"), new Contact("Bob")],
2
);
const serializedContactCollection = contactCollection.serialize();
serializedContactCollection.items.forEach((contact) => {
console.log(`User's name is ${contact.name}`)
});
答案 0 :(得分:0)
我找到了三种方法来执行此操作,具体取决于您是否要在ERROR in Cannot read property 'members' of undefined
中保留特定ModelInterface
的类型信息以及您想要的CollectionInterface
的类型参数成为。
首先,让我们修复CollectionInterface
和ModelInterface
的类型,它们应该使用generic constraints:
SerializedCollection
// A type that can serialize into a M, which must be a SerializedModel
interface ModelInterface<M extends SerializedModel> {
serialize(): M;
}
// Contact can serialize into SerializedContact
class Contact implements ModelInterface<SerializedContact> { /* ... */ }
// A serialized collection of Ms
interface SerializedCollection<M extends SerializedModel> {
count: number;
// I believe this is what you want (instead of { serialize(): M })
items: M[];
}
的单独类型参数这样,您可以将特定ModelInterface
的类型信息保留在ModelInterface
中。但是,我无法正确进行类型推断。在构造CollectionInterface
时,您需要明确声明类型参数。
下面Collection
的代码也使用了parameter properties,这只是做Collection
之类的更方便的方式。
class C { public x: number; constructor(x: number) { this.x = x } }
// A type that can serialize into a collection of Ms from the serializable Is
interface CollectionInterface<M extends SerializedModel, I extends ModelInterface<M>> {
count: number;
items: I[];
serialize(): SerializedCollection<M>;
}
// A class that implements CollectionInterface for a model M and model interface I
class Collection<M extends SerializedModel, I extends ModelInterface<M>> implements CollectionInterface<M, I> {
constructor(public items: I[], public count: number) {}
public serialize(): SerializedCollection<M> { /* ... */ }
}
// If you don't specify the type parameters TS will infer contactCollection to be
// Collection<SerializedModel, Contact> for some reason
const contactCollection = new Collection<SerializedContact, Contact>(
[new Contact("Bill"), new Contact("Bob")],
2
);
// type Contact[]
const contacts = contactCollection.items;
的{{1}}是CollectionInterface
这种方式的好处是不需要指定类型参数。但是,如果您需要知道下面的items
是ModelInterface<M>
而不仅仅是contacts
,则需要使用选项1。
Contact[]
ModelInterface<SerializedContact>[]
作为// A type that can serialize into a collection of Ms
interface CollectionInterface<M extends SerializedModel> {
count: number;
items: ModelInterface<M>[];
serialize(): SerializedCollection<M>;
}
// A class that implements CollectionInterface for a model M
class Collection<M extends SerializedModel> implements CollectionInterface<M> {
constructor(public items: ModelInterface<M>[], public count: number) {}
public serialize(): SerializedCollection<M> { /* ... */ }
}
// type Collection<SerializedContact>
const contactCollection = new Collection(
[new Contact("Bill"), new Contact("Bob")],
2
);
// type ModelInterface<SerializedContact>[]
const contacts = contactCollection.items;
的类型参数这类似于选项1,因为保留了特定ModelInterface
的类型信息,但是不需要像选项2一样指定类型参数。但是,它需要{{1 }}的CollectionInterface
。
ModelInterface
序列化集合后,所有这些选项的工作方式都相同:
Collection