【发布时间】:2021-07-19 20:01:41
【问题描述】:
我们有以下 OpenAPI 架构:
{
"openapi": "3.0.1",
"paths": {
"/v1/tool/breadcrumbs/{hierarchyId}/{categoryId}": {
"get": {
"tags": [
"V1-tool"
],
"summary": "Get Breadcrumbs details",
"operationId": "getBreadcrumbs",
"parameters": [
{
"name": "hierarchyId",
"in": "path",
"required": true,
"schema": {
"minimum": 1,
"type": "integer",
"format": "int32"
}
},
{
"name": "categoryId",
"in": "path",
"required": true,
"schema": {
"minimum": 1,
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "default response",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Kitten"
}
}
}
}
}
},
"security": [
{
"Auth": []
}
]
}
},
"/v1/tool/hierarchies": {
"get": {
"tags": [
"V1-tool"
],
"summary": "Get all available hierarchies ",
"operationId": "getAllHierarchies",
"responses": {
"200": {
"description": "default response",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/HierarchyResponse"
}
}
}
}
}
},
"security": [
{
"Auth": []
}
]
}
},
"/v1/tool/search/{hierarchyId}/{searchTerm}": {
"get": {
"tags": [
"V1-tool"
],
"summary": "Free text search categories for a given hierarchy",
"operationId": "searchBy",
"parameters": [
{
"name": "hierarchyId",
"in": "path",
"required": true,
"schema": {
"minimum": 1,
"type": "integer",
"format": "int32"
}
},
{
"name": "searchTerm",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "default response",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Kitten"
}
}
}
}
}
},
"security": [
{
"Auth": []
}
]
}
},
"/v1/tool/category/{hierarchyId}/{categoryId}": {
"get": {
"tags": [
"V1-tool"
],
"summary": "Get Category data needed to render a Table View in the Category Management tool",
"operationId": "getTableView",
"parameters": [
{
"name": "hierarchyId",
"in": "path",
"required": true,
"schema": {
"minimum": 1,
"type": "integer",
"format": "int32"
}
},
{
"name": "categoryId",
"in": "path",
"required": true,
"schema": {
"minimum": 1,
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "default response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TableViewResponse"
}
}
}
}
},
"security": [
{
"Auth": []
}
]
}
}
},
"components": {
"schemas": {
"Kitten": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Kitten"
]
},
"id": {
"type": "integer",
"format": "int32"
},
"name": {
"type": "string"
},
"uri": {
"type": "string"
}
}
},
"HierarchyResponse": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Hierarchy"
]
},
"id": {
"type": "integer",
"format": "int32"
},
"name": {
"type": "string"
}
}
},
"AliasCategoryResponse": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Alias"
]
},
"level": {
"type": "string"
},
"name": {
"type": "string"
},
"id": {
"type": "integer",
"format": "int32"
},
"uri": {
"type": "string"
}
}
},
"ChildCategoryResponse": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Category"
]
},
"level": {
"type": "string"
},
"name": {
"type": "string"
},
"id": {
"type": "integer",
"format": "int32"
},
"uri": {
"type": "string"
}
}
},
"GblSubheaderResponse": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Translation"
]
},
"brandCatalogId": {
"type": "integer",
"format": "int32"
},
"value": {
"type": "string"
}
}
},
"Item": {
"type": "object",
"properties": {
"type": {
"type": "string"
}
},
"oneOf": [
{
"$ref": "#/components/schemas/ChildCategoryResponse"
},
{
"$ref": "#/components/schemas/AliasCategoryResponse"
},
{
"$ref": "#/components/schemas/SubheaderResponse"
}
]
},
"ParentCategoryResponse": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"ParentCategory"
]
},
"id": {
"type": "integer",
"format": "int32"
},
"name": {
"type": "string"
}
}
},
"SubheaderResponse": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Subheader"
]
},
"name": {
"type": "string"
},
"translatedNames": {
"type": "array",
"items": {
"$ref": "#/components/schemas/GblSubheaderResponse"
}
}
}
},
"TableViewResponse": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"DefaultCategory"
]
},
"uri": {
"type": "string"
},
"level": {
"type": "string"
},
"name": {
"type": "string"
},
"id": {
"type": "integer",
"format": "int32"
},
"parentCategory": {
"$ref": "#/components/schemas/ParentCategoryResponse"
},
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Item"
}
}
}
}
},
"securitySchemes": {
"Auth": {
"type": "http",
"description": "Token Authentication e.g. Bearer <placeholder>",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
我们运行以下命令从上述模式文件生成流类型:
npx swagger-to-flowtype path/to/schema/file -d generated_types.js
这会产生以下输出:
// @flow strict
export type Kitten = { type: "Kitten", id: number, name: string, uri: string };
export type HierarchyResponse = { type: "Hierarchy", id: number, name: string };
export type AliasCategoryResponse = {
type: "Alias",
level: string,
name: string,
id: number,
uri: string
};
export type ChildCategoryResponse = {
type: "Category",
level: string,
name: string,
id: number,
uri: string
};
export type GblSubheaderResponse = {
type: "Translation",
brandCatalogId: number,
value: string
};
export type Item = { type: string };
export type ParentCategoryResponse = {
type: "ParentCategory",
id: number,
name: string
};
export type SubheaderResponse = {
type: "Subheader",
name: string,
translatedNames: Array<GblSubheaderResponse>
};
export type TableViewResponse = {
type: "DefaultCategory",
uri: string,
level: string,
name: string,
id: number,
parentCategory: ParentCategoryResponse,
items: Array<Item>
};
问题是Item类型定义为:
export type Item = { type: string };
我们希望将其定义为:
export type Item = ChildCategoryResponse | AliasCategoryResponse | SubheaderResponse;
我们的 OpenAPI 架构的相关部分是:
"Item": {
"type": "object",
"properties": {
"type": {
"type": "string"
}
},
"oneOf": [
{
"$ref": "#/components/schemas/ChildCategoryResponse"
},
{
"$ref": "#/components/schemas/AliasCategoryResponse"
},
{
"$ref": "#/components/schemas/SubheaderResponse"
}
]
},
我们最初认为swagger-to-flowtype 可能存在错误,但使用相同的模式通过swagger-typescript-api 生成 TypeScript 类型会输出类似的结果:
export enum Item {
Category = "Category",
Alias = "Alias",
Subheader = "Subheader",
}
...
export interface TableViewResponse {
type?: "DefaultCategory";
uri?: string;
level?: string;
name?: string;
/** @format int32 */
id?: number;
parentCategory?: ParentCategoryResponse;
items?: Item[];
}
请注意,在 Flow 和 TypeScript 类型中,我们应该有每个可能的对象形状的类型信息,Item 可能是,但我们没有任何此类类型信息。
这是一个项目数组的具体示例:
const items: Array<Item> = [
{
type: "Alias",
level: "3",
name: "name",
id: 42,
uri: "uri"
},
{
type: "Category",
level: "2",
name: "name",
id: 45,
uri: "uri"
}
]
希望现在可以清楚为什么 export type Item = { type: string }; 不是正确的类型定义。
问题:
是否有不同的架构可以生成所需的export type Item = ChildCategoryResponse | AliasCategoryResponse | SubheaderResponse 输出而不是当前的export type Item = { type: string }; 输出?
【问题讨论】:
标签: typescript openapi flowtype