Skip to content

The API document type designed for transformation tools.

Key features ​

  1. Independent package (so you can install and build your own tools)
  2. More close to typescript
  3. Support non literal object, like File, Date

Example ​

transform doc to UI

tsx
// type2cell.tsx
import type { DocNode } from '@tealina/doc-types'
import { DocKind } from '@tealina/doc-types'

export function type2cell(d: DocNode): ReactElement {
    // DocNode has a kind prop, can be simply use switch case
  switch (d.kind) {
    
    case DocKind.Primitive:
      return <ColorText type={d.type}>{d.type}</ColorText>

    case DocKind.Union:
        // use recursive calling do the transformation.
      return <>{injectDivider(d.types.map(t => type2cell(t, doc)))}</>
    
    case DocKind.Never:
      return <ColorText type="any">never</ColorText>

    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 has a kind prop, can be simply use switch case
  switch (d.kind) {
    
    case DocKind.Primitive:
      return <ColorText type={d.type}>{d.type}</ColorText>

    case DocKind.Union:
        // use recursive calling do the transformation.
      return <>{injectDivider(d.types.map(t => type2cell(t, doc)))}</>
    
    case DocKind.Never:
      return <ColorText type="any">never</ColorText>

    case DocKind.StringLiteral:
      return <ColorText type="string">"{d.value}"</ColorText>
    // ...  
  }
}

FAQ ​

Multiple http status code? ​

Not support directly, here some alternative way:,

  1. Add comment to handler, (when error handled in the interceptors)
ts
/**
 * @return
 *  -500 descript about it
 */
type ApiType=ApiHandler<Payload,Resonse>
/**
 * @return
 *  -500 descript about it
 */
type ApiType=ApiHandler<Payload,Resonse>
  1. Code inside your response type
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>

Type name losed ​

Use interface instead type, so the name will be retained.

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>
//...

Only use interface in the handler file is recommended

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>
  /**
   * The Tealina doc type version,
   * flow semver conventions.
   * format: [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>
  /**
   * The Tealina doc type version,
   * flow semver conventions.
   * format: [major].[minor]
   *  */
  docTypeVersion: number
}