{"record":{"id":"780d325c6297871f","repo":"can1357/oh-my-pi","slug":"invalid-generic-parameter-parameter-name","errorCode":null,"errorMessage":"invalid generic parameter \"${parameter.name}\"","messagePattern":"invalid generic parameter \"(.+?)\"","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/type.ts","lineNumber":2509,"sourceCode":"interface RuntimeGeneric extends Generic {\n\treadonly [GENERIC_META]: GenericMeta;\n}\n\n/** Schema arguments passed to a callback-bodied runtime generic. */\nexport 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 = \"\";","sourceCodeStart":2491,"sourceCodeEnd":2527,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/type.ts#L2491-L2527","documentation":"validateGenericParameters() enforces that every generic parameter name matches /^[A-Za-z-$]\\w*$/ — a valid identifier. A parameter name that is empty, starts with a digit, contains punctuation/spaces, or is otherwise not an identifier throws OmpTypeError. Generic parameters must be usable as placeholder names inside the definition body.","triggerScenarios":"Declaring a generic like generic('<T!>', 'T[]') or '<0T>', '<foo bar>', or an empty '<>' — parseGenericParameters feeds raw names into validation and any non-identifier name fails the regex.","commonSituations":"Typos in generic declarations; copying a string type name into a parameter position; building generic names programmatically and interpolating invalid characters; trailing commas or whitespace producing empty names.","solutions":["Rename the parameter to a valid identifier: letters, digits, underscore, or $, not starting with a digit","Check for stray characters (spaces, angle brackets left inside, punctuation) in the generic parameter list","If constructing the declaration dynamically, validate/escape the name before interpolation","Ensure the parameter list is not empty or malformed so no empty-string name reaches validation"],"exampleFix":"// before\nconst T = generic('<1st-Type>', 'array<1st-Type>'); // throws\n// after\nconst T = generic('<Type1>', 'array<Type1>');","handlingStrategy":"validation","validationCode":"const IDENT = /^[A-Za-z_$]\\w*$/;\nfunction assertValidParamName(name: string) {\n  if (!IDENT.test(name)) throw new Error(`generic parameter name invalid: ${name}`);\n}","typeGuard":"function isValidGenericName(name: string): boolean {\n  return /^[A-Za-z_$]\\w*$/.test(name);\n}","tryCatchPattern":"try {\n  const G = generic(decl, body);\n} catch (err) {\n  if (err instanceof OmpTypeError && err.message.includes('invalid generic parameter')) {\n    console.error(`Fix generic declaration \"${decl}\": parameter names must be identifiers`);\n  }\n  throw err;\n}","preventionTips":["Stick to conventional names: T, U, K, V, TProps","When generating declarations, sanitize names through the identifier regex first","Never interpolate raw user/config strings into parameter positions"],"tags":["generics","schema","naming","omptype"],"backgroundTag":"invalid-generic-parameter","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}