import { SyntaxKind, Type } from 'ts-morph' import { Ctx } from './types' export const match = ( k: K | undefined, pattern: { [key in K | '_']: () => R } ) => (k && pattern[k] ? pattern[k]() : pattern._()) export const evalList = async (ctx: Ctx, effectTyps: Type[]) => { const effectResults: string[] = [] for (const item of effectTyps ?? []) { effectResults.push(...(await ctx.evaluateType(ctx, item))) } return effectResults } export const applyFunc = (ctx: Ctx, fn: Type | undefined, val: string): Type => { const resultType = (() => { const baseTypes = fn ?.getBaseTypes() .flatMap((t) => t.getSymbol()?.getName() ?? []) if (!!fn?.getProperty('return') || baseTypes?.includes('Kind1')) { const [key, resultNode] = ctx.createResult( `(${ctx.typeToString(fn)} & { input: ${val} })['return']` ) ctx.removeResult(key) return resultNode ?.getType() .getProperty('output') ?.getTypeAtLocation(resultNode) } else { const [key, resultNode] = ctx.createResult( `ReturnType<${ctx.typeToString(fn)}>` ) ctx.removeResult(key) const resValueNode = resultNode ?.asKind(SyntaxKind.PropertySignature) ?.getChildAtIndexIfKind(2, SyntaxKind.TypeLiteral) ?.getProperty('output') ?.getChildAtIndexIfKind(2, SyntaxKind.TypeReference) const functionNode = resValueNode ?.getChildAtIndexIfKind(1, SyntaxKind.SyntaxList) ?.getFirstChildIfKind(SyntaxKind.FunctionType) if (functionNode) { const typeParameters = functionNode.getTypeParameters() ?? [] if (typeParameters.length > 0) { const constraint = typeParameters[0]?.getConstraint() if (constraint) { constraint?.replaceWithText(val) } else { typeParameters[0]?.setConstraint(val) } } return resValueNode?.getType() } } return undefined })() // TODO: Cleanup unwanted result node values if (!resultType) { throw new Error('Couldnt get result for function application') } return resultType }