import React from 'react'; import { JSONOutput } from 'typedoc'; import Link from '@docusaurus/Link'; import { TokenPunctuation, TokenPrimitive, TokenKeyword, TokenPlain, TokenLiteral, TokenType, TokenAttrName } from './tokens'; import renderReflection from './renderReflection'; import Params from './Params'; import Indent from './Indent'; type DeclarationType = JSONOutput.DeclarationReflection['type']; function renderTypeArgument( typeArguments: JSONOutput.SomeType[], params: Params ) { if (!typeArguments) { return null; } return ( <> < {typeArguments.reduce( (prev, curr) => ( <> {prev} {prev && , } {renderType(curr, params)} ), null )} > ); } export default function renderType(pt: DeclarationType, params: Params) { let shouldBreak = false; let nextParams: Params = params; switch (pt.type) { case 'reference': const ref = pt as JSONOutput.ReferenceType; let name = ref.name; // We must resolve reflections because of a bug in Typedoc with default exports const isLocalRef = 'id' in ref && !!params.resolveReflection(ref.id); if (isLocalRef) { name = params.resolveReflection(ref.id).name; } const nameToken = {name}; // TODO fix issue in multiple version docs // See blocking issue on https://github.com/facebook/docusaurus/issues/3372 return ( <> {isLocalRef ? ( {nameToken} ) : ( nameToken )} {renderTypeArgument(ref.typeArguments, params)} ); case 'intrinsic': return ( {(pt as JSONOutput.IntrinsicType).name} ); case 'union': const union = pt as JSONOutput.UnionType; shouldBreak = union.types.length > 2; return union.types .map((u) => renderType(u, params)) .reduce((prev, curr) => ( <> {prev} {shouldBreak &&
} {shouldBreak && } {!shouldBreak && ' '} {'| '} {curr} )); case 'intersection': const intersection = pt as JSONOutput.IntersectionType; shouldBreak = intersection.types.length > 2; nextParams = shouldBreak ? params.withIndent() : params; return intersection.types .map((u) => renderType(u, nextParams)) .reduce((prev, curr) => ( <> {prev} {shouldBreak && ( <>
)} {!shouldBreak && ' '} {'& '} {curr} )); case 'conditional': // Simplify conditionals as unions. API readers might not be familiar with // typescript, and unions are easier to understand. const cond = pt as JSONOutput.ConditionalType; if ( cond.falseType.type === 'intrinsic' && (cond.falseType as JSONOutput.IntrinsicType).name === 'never' ) { return renderType(cond.trueType, params); } return ( <> {renderType(cond.trueType, params)} {' | '} {renderType(cond.falseType, params)} ); case 'mapped': const mapped = pt as unknown as JSONOutput.MappedType; nextParams = params.withIndent(); return ( <> {'{'}
{'['} {mapped.parameter} {': '} {renderType(mapped.parameterType, nextParams)} {']'} {': '} {renderType(mapped.templateType, nextParams)}
{'}'} ); case 'literal': const literal = pt as JSONOutput.LiteralType; switch (typeof literal.value) { case 'bigint': case 'boolean': case 'number': return {String(literal.value)}; case 'undefined': return {String(literal.value)}; case 'object': if (literal.value === null) { return {String(literal.value)}; } break; case 'string': return {JSON.stringify(literal.value)}; } console.warn('Unhandled literal type', literal); throw new Error(`Unhandled literal ${literal.value}`); case 'array': const array = pt as JSONOutput.ArrayType; return ( <> Array < {renderType(array.elementType, params)} > ); case 'reflection': const reflection = pt as JSONOutput.ReflectionType; return renderReflection( reflection.declaration, params.withoutMemberLinks() ); case 'typeOperator': const to = pt as JSONOutput.TypeOperatorType; return ( <> {to.operator} {renderType(to.target, params)} ); case 'indexedAccess': const acc = pt as unknown as JSONOutput.IndexedAccessType; return ( <> {renderType(acc.objectType, params)} [ {renderType(acc.indexType, params)} ] ); case 'query': const query = pt as JSONOutput.QueryType; return ( <> typeof {renderType(query.queryType, params)} ); case 'predicate': const predicate = pt as JSONOutput.PredicateType; return ( <> {predicate.asserts && asserts } {predicate.name} is {predicate.targetType && renderType(predicate.targetType, params)} ); default: console.warn('Unhandled type', pt); throw new Error(`Unhandled type ${pt.type}`); } }