如果我理解正确,您正在要求对一个对象进行运行时检查,以确定它是否包含接口定义的所有属性。仅凭接口本身是不可能实现此目的的,因为与接口关联的类型信息并没有传递到运行时;换句话说,只有在我们运行TypeScript编译器时,接口才有用。
您可以创建包含接口所有属性的模式,然后循环遍历该模式,检查所有属性是否存在于您的对象中。以下是如何实现的例子。我已经将示例封装在用户定义的类型保护中。
export interface MyDocument {
id: string,
collection: string[];
}
const isMyDocument = (input: any): input is MyDocument => {
const schema: Record<keyof MyDocument, string> = {
id: 'string',
collection: 'array'
};
const missingProperties = Object.keys(schema)
.filter(key => input[key] === undefined)
.map(key => key as keyof MyDocument)
.map(key => new Error(`Document is missing ${key} ${schema[key]}`));
return missingProperties.length === 0;
}
const obj = {};
if (isMyDocument(obj)) {
obj.collection;
}
以下是上述代码可在TypeScript Playground中查看。
评论区问题的回答
以下是使用...
运算符扩展模式的方法。
interface ParentDocument {
id: string,
collection: [],
}
interface ChildDocument extends ParentDocument {
name: string;
}
const schemaParent: Record<keyof ParentDocument, string> = {
id: 'string',
collection: 'array'
};
const schemaChild: Record<keyof ChildDocument, string> = {
name: 'string',
...schemaParent,
};
constructor(data: any) { Object.assign(this,data); }
- voila - 无论你传递什么到这个类中,它都会自动遵循类上的任何属性,根据编译器...运行时是另一回事。 TypeScript应该在编译时捕获潜在问题,利用它的优势。如果你在进行类型转换时不确定你正在转换什么,并最终编写if语句进行检查,那么你就使用TypeScript错误了。 - Adam Jenkins