{"record":{"id":"926504b6f337674a","repo":"twbs/bootstrap","slug":"this-constructor-name-touppercase-option","errorCode":null,"errorMessage":"${this.constructor.NAME.toUpperCase()}: Option \"${property}\" provided type \"${valueType}\" but expected type \"${expectedTypes}\".","messagePattern":"(.+?): Option \"(.+?)\" provided type \"(.+?)\" but expected type \"(.+?)\"\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"js/src/util/config.js","lineNumber":57,"sourceCode":"\n  _mergeConfigObj(config, element) {\n    const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {} // try to parse\n\n    return {\n      ...this.constructor.Default,\n      ...(typeof jsonConfig === 'object' ? jsonConfig : {}),\n      ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}),\n      ...(typeof config === 'object' ? config : {})\n    }\n  }\n\n  _typeCheckConfig(config, configTypes = this.constructor.DefaultType) {\n    for (const [property, expectedTypes] of Object.entries(configTypes)) {\n      const value = config[property]\n      const valueType = isElement(value) ? 'element' : toType(value)\n\n      if (!new RegExp(expectedTypes).test(valueType)) {\n        throw new TypeError(\n          `${this.constructor.NAME.toUpperCase()}: Option \"${property}\" provided type \"${valueType}\" but expected type \"${expectedTypes}\".`\n        )\n      }\n    }\n  }\n}\n\nexport default Config\n","sourceCodeStart":39,"sourceCodeEnd":66,"githubUrl":"https://github.com/twbs/bootstrap/blob/6177d5f8497f2c08f9874f5221fd17ce5acd2ad7/js/src/util/config.js#L39-L66","documentation":"Whenever a component is constructed or reconfigured, Config._typeCheckConfig (util/config.js:51) walks the component's DefaultType table and regex-tests each option value's runtime type against expectations like 'number', 'boolean' or '(string|element|function)'. A failed test throws a TypeError naming the component, the option, the actual type and the expected type. Values read from data-bs-* attributes are auto-coerced (numeric strings to number, 'true' to boolean, JSON to object), but values passed programmatically in the config object are checked exactly as given.","triggerScenarios":"new bootstrap.Carousel(el, { interval: '5000' }) — string where DefaultType says 'number'; new bootstrap.Modal(el, { keyboard: 'false' }) — string instead of boolean; new bootstrap.Toast(el, { delay: '3000' }); a wrapper passing everything as strings from a form or dataset.","commonSituations":"Config objects assembled from strings (URL/query params, form fields, data attributes read via el.dataset which returns strings); framework wrappers with loose prop types; data-bs-* values that cannot auto-coerce (e.g. data-bs-delay=\"fast\").","solutions":["Pass native types in the JS config: interval: 5000 (number), keyboard: false (boolean).","Read the error message — it names the exact option and the expected type, mirroring the component's DefaultType table.","Convert string sources before init: Number(value) for numeric options, value === 'true' for booleans.","Fix and re-init: dispose the bad instance or call getOrCreateInstance again with corrected config."],"exampleFix":"// before\nnew bootstrap.Carousel(el, { interval: '5000' })\n// CAROUSEL: Option \"interval\" provided type \"string\" but expected type \"number\".\n\n// after\nnew bootstrap.Carousel(el, { interval: 5000 })","handlingStrategy":"validation","validationCode":"function configProblems(Component, config) {\n  const problems = []\n  for (const [key, expected] of Object.entries(Component.DefaultType)) {\n    const value = config[key]\n    if (value === undefined) continue\n    const actual = value === null ? 'null'\n      : value instanceof Element ? 'element'\n      : Array.isArray(value) ? 'array'\n      : typeof value\n    if (!new RegExp(expected).test(actual)) {\n      problems.push(`${Component.NAME}: \"${key}\" expected ${expected}, got ${actual}`)\n    }\n  }\n  return problems\n}\n\nconst problems = configProblems(bootstrap.Carousel, { interval: '5000' })\nif (problems.length) console.warn(problems.join('\\n')) // fix before constructing","typeGuard":"function typedConfig<T extends object>(config: T): T {\n  // compile-time counterpart: declare option types to mirror DefaultType\n  // (e.g. { interval: number; keyboard: boolean }) so strings fail at build time\n  return config\n}","tryCatchPattern":"try {\n  return new bootstrap.Modal(el, userConfig)\n} catch (err) {\n  if (err instanceof TypeError && /Option \".*\" provided type/.test(err.message)) {\n    reportConfigError(err.message) // surface the exact option/type pair to the caller\n    return null\n  }\n  throw err\n}","preventionTips":["Send real scalars through the JS API — never quoted numbers or booleans.","Convert string sources (dataset, query params, forms) with Number()/=== 'true' before init.","Treat Component.DefaultType as the source of truth for validation and docs.","In framework wrappers, type props to match DefaultType so mistakes surface at dev time."],"tags":["bootstrap","config","type-validation","options","typeerror"],"backgroundTag":"invalid-option-type","analyzedSha":"6177d5f8497f2c08f9874f5221fd17ce5acd2ad7","analyzedAt":"2026-08-22T03:20:03.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}