Relevant source files
The following files were used as context for generating this wiki page:
- packages/typescript/src/lib/type-table.ts
- packages/typescript/src/lib/base.ts
- packages/typescript/src/lib/remark-auto-type-table.ts
- packages/typescript/src/ui/auto-type-table.tsx
- packages/python/src/convert.ts
- packages/mdx/src/runtime/server.ts
- packages/typescript/src/lib/parse-tags.ts
- packages/story/src/type-tree/builder.ts
- packages/python/src/generated.ts
- packages/content/src/index.ts
- packages/story/src/utils/generate.ts
- packages/doc-gen/src/remark-ts2js.ts
- packages/api-docs/src/components/schema/index.tsx
- packages/typescript/src/ui/index.ts
- packages/base-ui/src/components/type-table.tsx
- packages/asyncapi/src/server/index.tsx
- packages/twoslash/src/index.ts
- packages/core/src/mdx-plugins/remark-structure.ts
- packages/typescript/src/index.ts
- packages/radix-ui/src/components/type-table.tsx
- packages/typescript/src/markdown.ts
- packages/python/fumapy/mksource/document_module.py
- packages/content/src/runtime.ts
- packages/preview/src/lib/source/storage.ts
- packages/python/src/components/index.tsx
- packages/openapi/src/utils/schema.ts
- packages/mdx/src/runtime/types.ts
- packages/mdx/src/plugins/index-file.ts
- packages/content-collections/src/configuration.ts
- packages/doc-gen/src/remark-docgen.ts
Overview
TypeScript type table extraction bridges raw source code types and rendered documentation interfaces by automatically inspecting TypeScript files, parsing JSDoc annotations, and transforming property definitions into interactive API tables packages/typescript/src/lib/base.ts:1-164, packages/typescript/src/ui/auto-type-table.tsx. Powered by ts-morph and unified remark plugins, the system extracts symbol metadata, processes tags like @default and @param, and serializes structured property entries for compile-time MDX replacement and runtime client rendering packages/typescript/src/lib/base.ts:167-230, packages/typescript/src/lib/remark-auto-type-table.ts.
Sources: packages/typescript/src/lib/base.ts:1-164, packages/typescript/src/lib/base.ts:167-230, packages/typescript/src/lib/remark-auto-type-table.ts:49-108, packages/typescript/src/ui/auto-type-table.tsx:1-80
Type Table Generator Architecture
Generator Factory and Configuration
The type table generator exposes public APIs for initializing type inspection environments and processing source declarations. The createGenerator function accepts GeneratorOptions, configuring optional project instances and cache mechanisms. If no custom Project instance is provided via options.project, createProject instantiates a new ts-morph Project pointing to tsconfigPath (defaulting to ./tsconfig.json) with skipAddingFilesFromTsConfig set to true.
export async function createProject(options: TypescriptConfig = {}): Promise<Project> {
const { Project } = await import('ts-morph');
return new Project({
tsConfigFilePath: options.tsconfigPath ?? './tsconfig.json',
skipAddingFilesFromTsConfig: true,
});
}
export function createGenerator(options: GeneratorOptions = {}) {
const cache = options?.cache ? options.cache : null;
let instance: Project | Promise<Project> | undefined = options?.project;
function getProject() {
if (instance) return instance;
return (instance = createProject(options));
}Sources: packages/typescript/src/lib/base.ts:86-101
| Option Property | Type | Default Value | Purpose |
|---|---|---|---|
tsconfigPath | string | './tsconfig.json' | Path to the TypeScript configuration file. |
cache | Cache | false | false | Enables caching for generated documentation results. |
project | Project | undefined | Pre-instantiated ts-morph project instance. |
allowInternal | boolean | false | Allows fields tagged with @internal. |
transform | Transformer | undefined | Custom function to modify property documentation entries. |
typeSimplifier | TypeSimplifierOptions | undefined | Configuration options for type simplification. |
Sources: packages/typescript/src/lib/base.ts:53-84
Note
When options.cache is active, documentation output is hashed using generateHash incorporating the file path, export name, file content, and package version before consulting the cache store.
Sources: packages/typescript/src/lib/base.ts:94-95, packages/typescript/src/lib/base.ts:129-134
Type Table Properties and Output Resolution
The BaseTypeTableProps and GenerateTypeTableOptions interfaces govern how individual type tables are located and generated from file paths or inline type definitions. The getTypeTableOutput helper resolves relative file paths against an optional basePath, reads source files asynchronously, and handles inline type strings.
export interface BaseTypeTableProps {
/**
* The path to source TypeScript file.
*/
path?: string;
/**
* Exported type name to generate from.
*/
name?: string;
/**
* Set the type to generate from.
*
* When used with `name`, it generates the type with `name` as export name.
*
* ```ts
* export const myName = MyType;
* ```
*
* When `type` contains multiple lines, `export const` is not added.
* You need to export it manually, and specify the type name with `name`.
*
* ```tsx
* <AutoTypeTable
* path="./file.ts"
* type={`import { ReactNode } from "react"
* export const MyName = ReactNode`}
* name="MyName"
* />
* ```
*/
type?: string;
}
export interface GenerateTypeTableOptions extends GenerateOptions {
/**
* base path to resolve `path` prop
*/
basePath?: string;
}Sources: packages/typescript/src/lib/type-table.ts:5-45
When type contains multiple lines, it is appended directly to the file content without modification. If type is a single line, it is wrapped in an exported type declaration using the specified name or falling back to $Fumadocs.
if (type && type.split('\n').length > 1) {
content += `\n${type}`;
} else if (type) {
typeName ??= '$Fumadocs';
content += `\nexport type ${typeName} = ${type}`;
}Sources: packages/typescript/src/lib/type-table.ts:61-66
Warning
If a requested export name is provided but yields an empty documentation output array, getTypeTableOutput throws an error stating that the export does not exist in the target file.
Sources: packages/typescript/src/lib/type-table.ts:74-75
Abstract Syntax Tree Extraction Pipeline
AST Processing and Call-Chain Execution
The AST extraction pipeline processes documentation requests through a strict sequence of calls initiated by remark plugins and handled by generator modules. The execution trace flows through remarkAutoTypeTable to createGenerator, then invokes generate before iterating over individual properties via getDocEntry.
Sources: packages/typescript/src/lib/remark-auto-type-table.ts:183-186, packages/typescript/src/lib/base.ts:153-153, packages/typescript/src/lib/base.ts:180-180
remarkAutoTypeTabletriggersgenerator.generateTypeTablewith configuration options and resolved paths. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:183-186createGeneratorresolves the source file within thets-morphproject instance and iterates over exported declarations matching the target name. Sources: packages/typescript/src/lib/base.ts:136-141generateconstructs anEntryContext, extracts top-level documentation comments, and retrieves all type properties. Sources: packages/typescript/src/lib/base.ts:167-182getDocEntryinspects each property symbol, evaluating JSDoc tags, optional status, and formatting types viats-morphand type simplifiers. Sources: packages/typescript/src/lib/base.ts:192-229
Warning
If a class declaration property name starts with a hash character (#), getDocEntry immediately returns undefined to filter out private class fields.
Sources: packages/typescript/src/lib/base.ts:196-198
Symbol Analysis and Declaration Handling
The generate function extracts top-level documentation comments from compiler symbols using getDocumentationComment with the program's type checker compiler object, converting display parts into strings via ts.displayPartsToString.
const comment = declaration
.getSymbol()
?.compilerSymbol.getDocumentationComment(program.getTypeChecker().compilerObject);Sources: packages/typescript/src/lib/base.ts:175-177
For each property symbol discovered on the declaration type, getDocEntry evaluates tags and formats types using ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope combined with ts.TypeFormatFlags.NoTruncation.
type: subType.getText(
context.declaration,
ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | ts.TypeFormatFlags.NoTruncation,
),Sources: packages/typescript/src/lib/base.ts:219-222
Important
When allowInternal is disabled (default false), any property containing an @internal JSDoc tag causes getDocEntry to abort and omit the entry entirely.
Sources: packages/typescript/src/lib/base.ts:204-205
Tag Parsing and Metadata Extraction
Call-Chain Execution Walkthrough
The extraction of metadata from JSDoc tags follows a precise sequence starting from the remark plugin AST traversal down to individual tag parsing.
remarkAutoTypeTableinitializes the transformation and invokesgenerateon the generator instance. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:183-186generateprocesses document entries and passes them tobuildTypePropfor property-level AST construction. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:49-52buildTypePropexecutesonItemfor each individualDocEntryrecord. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:53-53onItemcallsparseTagspassing the raw tag array attached to the entry. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:55-55parseTagsiterates over the raw tags, mapping recognized field names into structuredTypedTagsobjects. Sources: packages/typescript/src/lib/parse-tags.ts:17-44
Sources: packages/typescript/src/lib/remark-auto-type-table.ts:49-55, packages/typescript/src/lib/remark-auto-type-table.ts:183-186, packages/typescript/src/lib/parse-tags.ts:17-17
Tag Interpretation and Field Mapping
The parseTags function inspects each RawTag item, evaluating its name key to extract configuration values, parameter lists, and return descriptions. When the tag name matches default or defaultValue, the text content is assigned directly to typed.default.
for (const { name: key, text } of tags) {
if (key === 'default' || key === 'defaultValue') {
typed.default = text;
continue;
}Sources: packages/typescript/src/lib/parse-tags.ts:20-24
For param tags, text parsing splits strings around the first hyphen (-) separator to isolate the parameter name from its descriptive text. If no hyphen is present, the entire trimmed text serves as the parameter name with an empty description.
if (key === 'param') {
const sepIdx = text.indexOf('-');
const param = sepIdx === -1 ? text.trim() : text.slice(0, sepIdx).trim();
const description = sepIdx === -1 ? '' : text.slice(sepIdx + 1).trim();
typed.params ??= [];
typed.params.push({
name: param,
description,
});
continue;
}Sources: packages/typescript/src/lib/parse-tags.ts:26-37
| Tag Name Key | Mapped TypedTags Property | Interpretation Logic |
|---|---|---|
default, defaultValue | default | Assigns raw text value directly to the default property. |
param | params | Splits text at the first - character into parameter name and description. |
returns | returns | Assigns return documentation text directly to the returns property. |
Sources: packages/typescript/src/lib/parse-tags.ts:20-41
Note
Unrecognized tag names encountered during the iteration loop in parseTags are silently ignored without throwing errors or populating structured properties.
Sources: packages/typescript/src/lib/parse-tags.ts:20-43
Markdown Transformation and AST Replacement
Remark Plugin Traversal and Execution Flow
The remarkAutoTypeTable plugin operates as a unified transformer, walking the markdown Abstract Syntax Tree to locate automatic type table directives and replace them with interactive MDX flow elements. The plugin initializes a markdown renderer using either custom render options or the default markdownRenderer configured with Shiki syntax highlighting.
export function remarkAutoTypeTable(
config: RemarkAutoTypeTableOptions = {},
): Transformer<Root, Root> {
const {
name = 'auto-type-table',
outputName = 'TypeTable',
options: generateOptions = {},
remarkStringify = true,
generator = createGenerator(),
renderMarkdown,
renderType,
shiki,
} = config;
let renderer: MarkdownRenderer;
if (renderMarkdown && renderType) {
renderer = { renderMarkdownToHast: renderMarkdown, renderTypeToHast: renderType };
} else {
renderer = markdownRenderer(shiki);
if (renderMarkdown) renderer.renderMarkdownToHast = renderMarkdown;
if (renderType) renderer.renderTypeToHast = renderType;
}
Sources: packages/typescript/src/lib/remark-auto-type-table.ts:150-172
During AST traversal, the execution walkthrough follows a strict call chain from the remark transformer down to object expression builders:
remarkAutoTypeTableprocesses document entries and invokesgenerate. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:173-186generatecallsbuildTypeProppassing document entries and the markdown renderer. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:49-52buildTypePropexecutesonItemfor each individualDocEntryrecord. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:53-53onIteminvokesobjectBuilderto construct property-level expression objects. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:54-54objectBuilderaccumulates property nodes and expression statements for estree serialization. Sources: packages/typescript/src/lib/remark-auto-type-table.ts:15-35
Sources: packages/typescript/src/lib/remark-auto-type-table.ts:49-54, packages/typescript/src/lib/remark-auto-type-table.ts:173-186, packages/typescript/src/lib/remark-auto-type-table.ts:15-20
Prop Synthesis and AST Node Substitution
The buildTypeProp function constructs an Estree ObjectExpression mapping property names to their serialized metadata. Each entry renders its simplified type, full type description, required flag, default value, return description, parameters, and deprecation status into hast nodes before converting them into estree expressions.
async function buildTypeProp(
entries: DocEntry[],
renderer: MarkdownRenderer,
): Promise<ObjectExpression> {
async function onItem(entry: DocEntry) {
const node = objectBuilder();
const tags = parseTags(entry.tags);
node.addJsxProperty('type', await renderer.renderTypeToHast(entry.simplifiedType));
node.addJsxProperty('typeDescription', await renderer.renderTypeToHast(entry.type));
node.addExpressionNode('required', valueToEstree(entry.required));
if (entry.typeHref)
node.addExpressionNode('typeDescriptionLink', valueToEstree(entry.typeHref));
if (tags.default) node.addJsxProperty('default', await renderer.renderTypeToHast(tags.default));
if (tags.returns)
node.addJsxProperty('returns', await renderer.renderMarkdownToHast(tags.returns));
if (tags.params) {
node.addExpressionNode('parameters', {
type: 'ArrayExpression',
elements: await Promise.all(tags.params.map(onParam)),
});
}
if (entry.description) {
node.addJsxProperty('description', await renderer.renderMarkdownToHast(entry.description));
}
if (entry.deprecated) {
node.addExpressionNode('deprecated', valueToEstree(true));
}
return node.build();
}Sources: packages/typescript/src/lib/remark-auto-type-table.ts:49-84
The generated output forms an MdxJsxFlowElement node carrying attributes for the table ID, stringified JSON fallback, and embedded estree program body.
const rendered: MdxJsxFlowElement[] = [];
for (const doc of output) {
rendered.push({
type: 'mdxJsxFlowElement',
name: outputName,
attributes: [
{
type: 'mdxJsxAttribute',
name: 'id',
value: `type-table-${doc.id}`,
},
{
type: 'mdxJsxAttribute',
name: 'type',
value: {
type: 'mdxJsxAttributeValueExpression',
value: remarkStringify ? JSON.stringify(doc, null, 2) : '',
data: {
estree: {
type: 'Program',
sourceType: 'module',
body: [
{
type: 'ExpressionStatement',
expression: await buildTypeProp(doc.entries, renderer),
},
],
},
},
},
},
...attributes,
],
children: [],
});
}Sources: packages/typescript/src/lib/remark-auto-type-table.ts:187-223
Warning
When remarkStringify is enabled in configuration options, JSON.stringify populates the attribute value string alongside the compiled estree program expression to support legacy stringifiers.
Sources: packages/typescript/src/lib/remark-auto-type-table.ts:157-157, packages/typescript/src/lib/remark-auto-type-table.ts:202-205
Interactive Client Table Rendering
Runtime Component and Hast Conversion
The AutoTypeTable component provides server-side or runtime rendering for interactive type tables by invoking the specified generator and transforming parsed doc entries into UI nodes. When renderType and renderMarkdown functions are omitted from AutoTypeTableProps, a default Markdown renderer initialized with Shiki options converts type signatures and docstrings into hast trees, which toJsx then transforms into React elements using toJsxRuntime.
export async function AutoTypeTable({
generator,
options,
renderType,
renderMarkdown,
shiki,
name,
path,
type,
...props
}: AutoTypeTableProps) {
if (!renderType || !renderMarkdown) {
const renderer = markdownRenderer(shiki);
renderType ??= async (v) => toJsx(await renderer.renderTypeToHast(v));
renderMarkdown ??= async (v) => toJsx(await renderer.renderMarkdownToHast(v));
}Sources: packages/typescript/src/ui/auto-type-table.tsx:23-38
The helper function toJsx wraps toJsxRuntime with the React JSX runtime and default MDX components while explicitly setting the img component override to undefined.
function toJsx(hast: Nodes) {
return toJsxRuntime(hast, {
...JsxRuntime,
components: { ...defaultMdxComponents, img: undefined },
});
}Sources: packages/typescript/src/ui/auto-type-table.tsx:81-86
Note
The AutoTypeTable component exports from packages/typescript/src/ui/index.ts, making it available for direct inclusion in client and server component contexts.
Sources: packages/typescript/src/ui/index.ts:1-1
Table Display and Collapsible Row Management
The TypeTable component from fumadocs-ui renders a container holding individual property rows using the Item subcomponent, utilizing translation notes keyed by type table. Each entry maps property keys to TypeNode definitions containing type elements, descriptions, defaults, required flags, and parameter lists.
export function TypeTable({
id,
type,
className,
...props
}: { type: Record<string, TypeNode> } & ComponentProps<'div'>) {
const t = useTranslations({ note: 'type table' });
return (
<div
id={id}
className={cn(
'@container flex flex-col p-1 bg-fd-card text-fd-card-foreground rounded-2xl border my-6 text-sm overflow-hidden',
className,
)}
{...props}
>
<div className="flex font-medium items-center px-3 py-1 not-prose text-fd-muted-foreground">
<p className="w-1/4">{t('Prop')}</p>
<p className="@max-xl:hidden">{t('Type')}</p>
</div>
{Object.entries(type).map(([key, value]) => (
<Item key={key} parentId={id} name={key} item={value} />
))}
</div>
);
}Sources: packages/radix-ui/src/components/type-table.tsx:52-78
| Property | Type / Interface | Default / Meaning |
|---|---|---|
description | ReactNode | Additional description of the field. |
type | ReactNode | Short type signature displayed in the main row view. |
typeDescription | ReactNode | Full type signature displayed in the collapsible drawer. |
typeDescriptionLink | string | Optional hyperlink destination for the type. |
default | ReactNode | Default value expression or tag rendering. |
required | boolean | Indicates if the property is mandatory (false appends ?). |
deprecated | boolean | Applies line-through and muted styling when active. |
parameters | ParameterNode[] | List of parameter names and descriptions for function types. |
returns | ReactNode | Return value description for function types. |
Sources: packages/radix-ui/src/components/type-table.tsx:11-48
The Item component wraps each table row inside a Collapsible primitive, synchronizing open state changes with browser history hash updates so that deep links matching #${parentId}-${name} automatically expand the targeted property row upon load.
function Item({
parentId,
name,
item: {
parameters = [],
description,
required = false,
deprecated,
typeDescription,
default: defaultValue,
type,
typeDescriptionLink,
returns,
},
}: {
parentId?: string;
name: string;
item: TypeNode;
}) {
const t = useTranslations({ note: 'type table' });
const [open, setOpen] = useState(false);
const id = parentId ? `${parentId}-${name}` : undefined;
useEffect(() => {
const hash = window.location.hash;
if (!id || !hash) return;
if (`#${id}` === hash) setOpen(true);
}, [id]);
return (
<Collapsible
id={id}
open={open}
onOpenChange={(v) => {
if (v && id) {
window.history.replaceState(null, '', `#${id}`);
}
setOpen(v);
}}
className={cn(
'rounded-xl border overflow-hidden scroll-m-20 transition-all',
open ? 'shadow-sm bg-fd-background not-last:mb-2' : 'border-transparent',
)}
>Sources: packages/radix-ui/src/components/type-table.tsx:80-123
Warning
If a window location hash matches a property row identifier on mount, the useEffect hook forces open to true, overriding default closed states for direct URL navigation.
Sources: packages/radix-ui/src/components/type-table.tsx:103-107
Related
On This Page
OverviewType Table Generator ArchitectureGenerator Factory and ConfigurationType Table Properties and Output ResolutionAbstract Syntax Tree Extraction PipelineAST Processing and Call-Chain ExecutionSymbol Analysis and Declaration HandlingTag Parsing and Metadata ExtractionCall-Chain Execution WalkthroughTag Interpretation and Field MappingMarkdown Transformation and AST ReplacementRemark Plugin Traversal and Execution FlowProp Synthesis and AST Node SubstitutionInteractive Client Table RenderingRuntime Component and Hast ConversionTable Display and Collapsible Row ManagementRelated