import React from 'react'; import type { ReferenceType } from '../../reference/index.js'; import { findSymbolByMember } from '../../tools/ReferenceTools.js'; import TypeAliasHint from '../TypeAliasHint.js'; import ReferenceTypeView from './ReferenceTypeView.js'; interface TypeProps { def?: ReferenceType; ignoreUndefined?: boolean; isOptional?: boolean; } const Type: React.FunctionComponent = ({ def, ignoreUndefined = false, isOptional = false }) => { if (!def) { return <>void; } switch (def.type) { case 'union': { const types = [...def.types]; const trueIndex = types.findIndex(type => type.type === 'intrinsic' && type.name === 'true'); const falseIndex = types.findIndex(type => type.type === 'intrinsic' && type.name === 'false'); if (trueIndex !== -1 && falseIndex !== -1) { types.splice(trueIndex, 1, { type: 'intrinsic', name: 'boolean' }); types.splice(falseIndex, 1); } if (types.length === 2) { const undefIndex = types.findIndex(type => type.type === 'intrinsic' && type.name === 'undefined'); if (undefIndex !== -1) { const defIndex = +!undefIndex; // 0 => 1, 1 => 0 to find the type that isn't undefined if (ignoreUndefined) { return ; } return ( <> ? ); } } if (isOptional && types.length === 1) { return ( <> ? ); } return ( <> {types.map((type, idx) => ( {idx === 0 ? '' : ' | '} ))} ); } case 'intersection': { return ( <> {def.types.map((type, idx) => ( {idx === 0 ? '' : ' & '} ))} ); } case 'array': { if (!def.elementType) { return <>Array; } if (def.elementType.type === 'union') { return ( <> {isOptional ? '?' : ''} ( )[] ); } return ( <> {isOptional ? '?' : ''} [] ); } case 'literal': { return ( <> {isOptional ? '?' : ''} {def.value} ); } case 'reflection': { const { signatures } = def.declaration; if (signatures?.length) { const [signature] = signatures; switch (signature.kind) { case 'callSignature': { return ( <> {isOptional ? '?' : ''}( {signature.parameters.length ? signature.parameters.map((param, i) => ( {i === 0 ? null : ', '} {param.name}: )) : null} ) => ); } default: { // eslint-disable-next-line no-console,@typescript-eslint/restrict-template-expressions console.log(`unknown reflection signature type: ${signature.kind}`); return null; } } } // if it doesn't have a signature, it's an anonymous object (as far as we know) return ( <> {isOptional ? '?' : ''} object ); } case 'reference': { if (def.id) { const referencedDesc = findSymbolByMember('id', def.id); if (referencedDesc) { const { symbol: referencedType } = referencedDesc; if (referencedType.kind === 'typeAlias') { return ; } // TODO forward the CORRECT type arguments if this is a superclass return ( ); } } return ; } case 'tuple': { return ( <> [ {def.elements.map((type, idx) => ( {idx === 0 ? '' : ', '} ))} ] ); } case 'named-tuple-member': { return ( <> {def.name}: ); } case 'optional': { return ( <> ? ); } case 'typeOperator': { return ( <> {def.operator} ); } default: { return ( <> {isOptional ? '?' : ''} {def.name} ); } } }; export default Type;