使用openapi-typescript-codegen时,Swagger Schema为何生成Record<string, any>模型?
问题描述
我在Swagger的components/schemas中定义了BuildFruitBody结构:
"schemas": { "BuildFruitBody": { "properties": { "id": { "type": "number", "format": "double" }, "name": { "type": "string" } }, "type": "object", "additionalProperties": true } }
执行命令 npx openapi-typescript-codegen -i ./swagger.json -o src/services/api -c axios 生成Axios客户端后,得到的模型却是:
/* generated using openapi-typescript-codegen -- do no edit */ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ export type BuildFruitBody = Record<string, any>;
完整的swagger.json内容如下:
{ "components": { "examples": {}, "headers": {}, "parameters": {}, "requestBodies": {}, "responses": {}, "schemas": { "BuildFruitBody": { "properties": { "id": { "type": "number", "format": "double" }, "name": { "type": "string" } }, "type": "object", "additionalProperties": true } }, "securitySchemes": {} }, "info": { "title": "backend", "contact": {} }, "openapi": "3.0.0", "paths": { "/swagger.json": { "get": { "operationId": "Get", "responses": { "200": { "description": "Ok", "content": { "application/json": { "schema": { "type": "string" } } } } }, "tags": [ "swagger" ], "security": [], "parameters": [] } }, "/fruit": { "post": { "operationId": "Get", "responses": { "200": { "description": "Ok", "content": { "application/json": { "schema": { "type": "string" } } } } }, "tags": [ "fruit" ], "security": [], "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BuildFruitBody" } } } } } } }, "servers": [ { "url": "/" } ] }
为什么生成的模型没有匹配Schema定义?我操作有误吗?
原因与解决方法
核心原因
问题出在additionalProperties: true配置上。openapi-typescript-codegen处理带有该配置的对象Schema时,默认会将其转换为Record<string, any>类型——因为additionalProperties: true表示对象可以包含任意未定义的键值对,工具会优先识别这种“任意对象”特性,从而忽略显式定义的properties字段。
解决方法
根据你的需求,有两种处理方式:
移除
additionalProperties或设为false
如果接口不允许传入Schema定义之外的额外属性,直接删除additionalProperties字段,或者将其设为false:"BuildFruitBody": { "properties": { "id": { "type": "number", "format": "double" }, "name": { "type": "string" } }, "type": "object", "additionalProperties": false }重新生成客户端后,会得到包含显式字段的TypeScript类型:
export type BuildFruitBody = { id?: number; name?: string; };保留额外属性同时保留显式字段
如果确实需要允许额外属性,但又希望TypeScript识别显式定义的字段,可以将additionalProperties设为具体类型(比如any),而非直接设为true:"BuildFruitBody": { "properties": { "id": { "type": "number", "format": "double" }, "name": { "type": "string" } }, "type": "object", "additionalProperties": { "type": "any" } }这种情况下,生成的类型会同时包含显式字段和任意额外属性:
export type BuildFruitBody = { id?: number; name?: string; } & Record<string, any>;
内容的提问来源于stack exchange,提问作者defraggled

