递归类型别名属性访问



我正在尝试键入这个类,它最初是用JavaScript编写的。

这是代码片段。

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不仅能猜测我在编译时传递给它的东西的类型(比如变成SchemaDefinitionSchema(,还能支持递归调用,并且仍然能够猜测返回输出中嵌套属性的类型,在不存在的属性上调用中间件,或者调用类型错误的中间件。

我在Middlewares属性中的回调中遇到问题,该回调缺少一些环绕的paren。

此外,该代码看起来更干净,使用for-in循环更容易处理。我也借此机会将其作为一个函数,因为在这种情况下使用类并没有真正的附加值。

我不得不使用一些丑陋的as类型断言,但据我所知,我不明白为什么不在这种情况下使用,因为它是一个联合类型,它有助于编译器了解情况。

type SchemaDefinition<Schema> = {[Key in keyof Schema]: Schema[Key][] | {[K in keyof Schema[Key]]: Schema[Key][K][]}};
type Middlewares<Schema> = {[Key in keyof Schema]?: ((value: Schema[Key]) => Schema[Key]) | Middlewares<Schema[Key]>};
const createObjectGenerator = <Schema>(schemaDefinition = {} as SchemaDefinition<Schema>) => {
return (middlewares = {} as Middlewares<Schema>) => {
const schema = {} as Schema;
for (const property in schemaDefinition) {
if (!schemaDefinition.hasOwnProperty(property)) {
continue;
}
const values = schemaDefinition[property];
if (Array.isArray(values)) {
const value = values[Math.floor(Math.random() * values.length)];
if (typeof middlewares !== "undefined") {
const middleware = middlewares[property];
if (typeof middleware === "function") {
schema[property] = middleware(value);
continue;
}
}
schema[property] = value;
continue;
}
if (typeof values === "object") {
if (typeof middlewares !== "undefined") {
const nestedMiddlewares = middlewares[property];
if (typeof nestedMiddlewares === "object") {
schema[property] = createObjectGenerator(values as Schema[typeof property])(nestedMiddlewares) as Schema[typeof property];
continue;
}  
}
schema[property] = createObjectGenerator(values as Schema[typeof property])() as Schema[typeof property];
continue;
}
}
return schema;
}
}

最新更新