{"record":{"id":"32dc6bff28b24dd1","repo":"can1357/oh-my-pi","slug":"generic-declarations-require-at-least-one-paramete","errorCode":null,"errorMessage":"generic declarations require at least one parameter","messagePattern":"generic declarations require at least one parameter","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/type.ts","lineNumber":2514,"sourceCode":"export interface GenericArguments {\n\treadonly [name: string]: BaseType;\n}\n\nexport interface GenericBuilder {\n\t(definition: (arguments_: GenericArguments) => unknown, hkt?: unknown): Generic;\n\t(definition: unknown, hkt?: unknown): Generic;\n}\n\nfunction validateGenericParameters(parameters: readonly GenericParameter[]): void {\n\tconst names = new Set<string>();\n\tfor (const parameter of parameters) {\n\t\tif (!/^[A-Za-z_$]\\w*$/.test(parameter.name)) {\n\t\t\tthrow new OmpTypeError(`invalid generic parameter \"${parameter.name}\"`);\n\t\t}\n\t\tif (names.has(parameter.name)) throw new OmpTypeError(`duplicate generic parameter \"${parameter.name}\"`);\n\t\tnames.add(parameter.name);\n\t}\n\tif (parameters.length === 0) throw new OmpTypeError(\"generic declarations require at least one parameter\");\n}\n\nfunction parseGenericParameters(source: string): GenericParameter[] {\n\tconst trimmed = source.trim();\n\tconst body = trimmed.startsWith(\"<\") && trimmed.endsWith(\">\") ? trimmed.slice(1, -1) : trimmed;\n\tconst parts: string[] = [];\n\tlet start = 0;\n\tlet depth = 0;\n\tlet quote = \"\";\n\tfor (let index = 0; index < body.length; index++) {\n\t\tconst char = body[index];\n\t\tif (quote !== \"\") {\n\t\t\tif (char === quote && body[index - 1] !== \"\\\\\") quote = \"\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"'\" || char === '\"' || char === \"`\") quote = char;\n\t\telse if (char === \"<\" || char === \"(\" || char === \"[\") depth++;\n\t\telse if (char === \">\" || char === \")\" || char === \"]\") depth = Math.max(0, depth - 1);","sourceCodeStart":2496,"sourceCodeEnd":2532,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/type.ts#L2496-L2532","documentation":"validateGenericParameters() requires at least one generic parameter; an empty declaration throws OmpTypeError. A generic with zero parameters has nothing to instantiate, so it's a usage mistake of the generic() API.","triggerScenarios":"Calling generic('', '...') or generic('<>', '...') — the parser strips angle brackets, produces zero parts, and the length===0 check fires. Also happens when a dynamically built parameter list string ends up empty.","commonSituations":"Template-driven codegen emitting an empty parameter list when no type variables were collected; refactoring away the only parameter but keeping the generic wrapper; accidentally passing the body as the parameter argument.","solutions":["Provide at least one parameter: generic('<T>', 'T[]')","If the type has no type variables, drop generic() and declare it directly with type()","Fix the codegen/template so it only emits generic() when at least one parameter exists","Check argument order — ensure you didn't pass the body where the parameter declaration belongs"],"exampleFix":"// before\nconst T = generic('', 'string[]'); // throws\n// after\nconst T = type('string[]'); // no generics needed\nconst G = generic('<T>', 'T[]'); // or a real generic","handlingStrategy":"validation","validationCode":"function assertNonEmptyGenericDecl(decl: string) {\n  const inner = decl.trim().replace(/^<|>$/g, '').trim();\n  if (!inner) throw new Error('generic declaration needs at least one parameter');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const G = generic(decl, body);\n} catch (err) {\n  if (err instanceof OmpTypeError && err.message === 'generic declarations require at least one parameter') {\n    throw new Error(`\"${decl}\" declares no parameters — use type() instead of generic()`);\n  }\n  throw err;\n}","preventionTips":["Only wrap in generic() when at least one type variable exists","Guard codegen paths that may emit empty parameter lists","Double-check argument order: declaration first, body second"],"tags":["generics","schema","empty-input","omptype"],"backgroundTag":"invalid-generic-parameter","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}