API 文档类型
这是一个专为转换工具而设计的 API 文档类型 它有这些关键特性:
- 独立的包,方便你基于它编写转换工具
- 类型定义偏向 Typescript
- 支持不可序列化的类型, 比如 File, Date
案列
文档转成 UI
tsx
// type2cell.tsx
import type { DocNode } from "@tealina/doc-types";
import { DocKind } from "@tealina/doc-types";
export function type2cell(d: DocNode): ReactElement {
// 每个节点都有属性 DocNode,方便使用switch case
switch (d.kind) {
case DocKind.Primitive:
return <ColorText type={d.type}>{d.type}</ColorText>;
case DocKind.Union:
// 递归调用
return <>{injectDivider(d.types.map((t) => type2cell(t, doc)))}</>;
case DocKind.StringLiteral:
return <ColorText type="string">"{d.value}"</ColorText>;
// ...
}
}
// type2cell.tsx
import type { DocNode } from "@tealina/doc-types";
import { DocKind } from "@tealina/doc-types";
export function type2cell(d: DocNode): ReactElement {
// 每个节点都有属性 DocNode,方便使用switch case
switch (d.kind) {
case DocKind.Primitive:
return <ColorText type={d.type}>{d.type}</ColorText>;
case DocKind.Union:
// 递归调用
return <>{injectDivider(d.types.map((t) => type2cell(t, doc)))}</>;
case DocKind.StringLiteral:
return <ColorText type="string">"{d.value}"</ColorText>;
// ...
}
}
FAQ
返回值有多个状态码,类型如何声明?
并没有直接的支持, 你可以通过其他方式:,
- 在注释中提及, (统一在拦截器中处理错误)
ts
/**
* @return
* -500 descript about it
*/
type ApiType = ApiHandler<Payload, Resonse>;
/**
* @return
* -500 descript about it
*/
type ApiType = ApiHandler<Payload, Resonse>;
- 状态码写进返回值内部
ts
type BaseResponse<T> = {
code: number;
data: T;
};
interface NamedResponse
extends BaseResponse<{ code: 200; data: { status: "ok" } }> {}
type ApiType = ApiHandler<Payload, NamedResponse>;
type BaseResponse<T> = {
code: number;
data: T;
};
interface NamedResponse
extends BaseResponse<{ code: 200; data: { status: "ok" } }> {}
type ApiType = ApiHandler<Payload, NamedResponse>;
文档中类型名称没有保留
使用 interface
而不是 type
, 名字会被保留
ts
type UserType = TypeFromCalculationUnitily<{ name: string }>;
interface User extends UserType {}
type ApiType = ApiHandler<Payload, User>;
//...
type UserType = TypeFromCalculationUnitily<{ name: string }>;
interface User extends UserType {}
type ApiType = ApiHandler<Payload, User>;
//...
推荐只在 API 文件中使用 interface
More detail
ts
export const DocKind = {
// more close to typescript
/** eg: string,number */
Primitive: 0,
/** types that has method, eg: Date, File, Blob */
NonLiteralObject: 1,
Tuple: 2,
Union: 3,
EntityRef: 4,
Never: 5,
Record: 6,
StringLiteral: 7,
NumberLiteral: 8,
EnumRef: 9,
EnumMemberRef: 10,
Array: 11,
RecursionTuple: 12,
RecursionEntity: 13,
} as const;
export interface Kind {
isOptional?: true;
comment?: string;
jsDoc?: Partial<Record<string, string>>;
}
export interface PrimitiveType extends Kind {
kind: DocKind["Primitive"]; // every DocNode has a kind prop
type: string;
}
// ...
export type DocNode =
| PrimitiveType
| ObjectType
| TupleType
| UnionType
| RefType
| EnumRefType
| EnumMemberRefType
| RecordType
| NumberLiteral
| StringLiteral
| NeverType
| ArrayType
| RecursionTuple
| RecursionEntity;
export interface DocItem {
body?: DocNode;
response?: DocNode;
query?: DocNode;
params?: DocNode;
headers?: DocNode;
comment?: string;
}
type HttpMethod = string;
type Endpoint = string;
type Id = number;
export interface ApiDoc {
apis: Record<HttpMethod, Record<Endpoint, DocItem>>;
entityRefs: Record<Id, Entity>;
enumRefs: Record<Id, EnumEntity>;
tupleRefs: Record<Id, TupleEntity>;
/**
* 文档版本,遵循标准语义化版本规则,
* 格式: [major].[minor]
* */
docTypeVersion: number;
}
export const DocKind = {
// more close to typescript
/** eg: string,number */
Primitive: 0,
/** types that has method, eg: Date, File, Blob */
NonLiteralObject: 1,
Tuple: 2,
Union: 3,
EntityRef: 4,
Never: 5,
Record: 6,
StringLiteral: 7,
NumberLiteral: 8,
EnumRef: 9,
EnumMemberRef: 10,
Array: 11,
RecursionTuple: 12,
RecursionEntity: 13,
} as const;
export interface Kind {
isOptional?: true;
comment?: string;
jsDoc?: Partial<Record<string, string>>;
}
export interface PrimitiveType extends Kind {
kind: DocKind["Primitive"]; // every DocNode has a kind prop
type: string;
}
// ...
export type DocNode =
| PrimitiveType
| ObjectType
| TupleType
| UnionType
| RefType
| EnumRefType
| EnumMemberRefType
| RecordType
| NumberLiteral
| StringLiteral
| NeverType
| ArrayType
| RecursionTuple
| RecursionEntity;
export interface DocItem {
body?: DocNode;
response?: DocNode;
query?: DocNode;
params?: DocNode;
headers?: DocNode;
comment?: string;
}
type HttpMethod = string;
type Endpoint = string;
type Id = number;
export interface ApiDoc {
apis: Record<HttpMethod, Record<Endpoint, DocItem>>;
entityRefs: Record<Id, Entity>;
enumRefs: Record<Id, EnumEntity>;
tupleRefs: Record<Id, TupleEntity>;
/**
* 文档版本,遵循标准语义化版本规则,
* 格式: [major].[minor]
* */
docTypeVersion: number;
}