【发布时间】:2020-12-01 17:58:49
【问题描述】:
我正在尝试键入这个最初用 JavaScript 编写的类。
这里是代码sn-p。
type SchemaDefinition<Schema> = {[Key in keyof Schema]: Schema[Key][] | {[K in keyof Schema[Key]]: SchemaDefinition<Schema[Key][K]>}};
type Middlewares<Schema> = {[Key in keyof Schema]: (value: Schema[Key]) => Schema[Key] | {[K in keyof Schema[Key]]: Middlewares<Schema[Key][K]>}};
class ObjectGenerator<Schema> {
private schemaDefinition: SchemaDefinition<Schema>;
constructor(schemaDefinition: SchemaDefinition<Schema> = {} as SchemaDefinition<Schema>) {
this.schemaDefinition = schemaDefinition;
}
generate(middlewares: Middlewares<Schema> = {} as Middlewares<Schema>): Schema {
const {schemaDefinition} = this;
return Object.entries(schemaDefinition).reduce((schema, [property, values]) => {
if (Array.isArray(values)) {
return {...schema, [property]: (middlewares[property] || ((x: any): any => x))(values[Math.floor(Math.random() * values.length)])};
} else if (typeof values === "object") {
return {...schema, [property]: new ObjectGenerator(values).generate(middlewares[property])};
}
return schema;
}, {} as Schema);
}
}
我得到的错误是。
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Middlewares<Schema>'. No index signature with a parameter of type 'string' was found on type 'Middlewares<Schema>'
我对此的期望是 TypeScript 不仅可以猜测我在编译时传递给它的东西的类型(比如 Schema 变成了 SchemaDefinition),而且还支持递归调用,并且仍然能够猜测返回输出中嵌套属性的类型,以便客户端在尝试访问不存在的嵌套属性、在不存在的属性上调用中间件或使用类型错误。
【问题讨论】:
-
Object.entries()是问题所在,因为编译器不能确定它知道所有对象的属性;请参阅this answer 了解更多信息。如果你想回避它,你可以做一个像Object.entries(schemaDefinition) as Array<[keyof Schema, Schema[keyof Schema]]>这样的断言(不比{} as SchemaDefinition<Schema>差,这对我来说似乎更可疑)。如果这是您的主要问题,我可能会将问题作为引用Object.entries()的其他人的副本来关闭;否则请详细说明。祝你好运! -
谢谢你。实际上,使用 for-in 循环有助于使事情变得更清晰。我忘记了回调中间件中联合周围的一些括号。通过添加一些丑陋的类型断言,我终于得到了一些有用的东西。谢谢。我会回答我自己的问题。
标签: typescript recursion