oxc-project/oxc · warning · OxcDiagnostic
`button` elements must have a valid `type` attribute.
Error message
`button` elements must have a valid `type` attribute.
What it means
Diagnostic from the oxlint rule `react/button-has-type` (plugin `react`, category `restriction`). It fires when a `<button>` (or `createElement('button', ...)`) HAS a `type` attribute but its value is not statically one of the enabled literals. The rule accepts string literals, template literals with a single quasi (no interpolation), expression containers wrapping those, and conditional expressions where BOTH branches are valid. Anything else - identifiers (`type={foo}`), interpolated templates, other expression types - is rejected because the value cannot be proven. The `button`/`submit`/`reset` config flags (all default `true`) narrow the allowed set, and the help text lists the enabled values (e.g. turning `reset: false` on makes `type="reset"` invalid).
Source
Thrown at crates/oxc_linter/src/rules/react/button_has_type.rs:27
ast::{
Argument, Expression, JSXAttributeItem, JSXAttributeValue, JSXElementName,
ObjectPropertyKind,
},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use schemars::JsonSchema;
use serde::Deserialize;
fn missing_type_prop(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("`button` elements must have an explicit `type` attribute.")
.with_help("Add a `type` attribute to the `button` element.")
.with_label(span)
}
fn invalid_type_prop(span: Span, allowed_types: &str) -> OxcDiagnostic {
OxcDiagnostic::warn("`button` elements must have a valid `type` attribute.")
.with_help(format!(
"Change the `type` attribute to one of the allowed values: {allowed_types}."
))
.with_label(span)
}
#[derive(Debug, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct ButtonHasType {
/// If true, allow `type="button"`.
button: bool,
/// If true, allow `type="submit"`.
submit: bool,
/// If true, allow `type="reset"`.
reset: bool,
}
impl Default for ButtonHasType {View on GitHub (pinned to e1e7af627c)
Solutions
- Use an allowed literal: `type="button"`, `type="submit"`, or `type="reset"`
- For dynamic values, express both possibilities as literals: `type={isPrimary ? 'submit' : 'button'}`
- If you disabled a value in config (e.g. `reset: false`), either re-enable it or stop using that value
- If the value is genuinely unresolvable statically, widen with a comment/directive or move the choice into a wrapper component with literal props
Example fix
// before
<button type={btnKind}>Go</button>
// after
<button type={btnKind === 'primary' ? 'submit' : 'button'}>Go</button> Defensive patterns
Strategy: validation
Validate before calling
npx oxlint --react/button-has-type src/
Type guard
// Constrain button types at the type level:
type ButtonType = 'button' | 'submit' | 'reset';
const isButtonType = (v: string): v is ButtonType =>
v === 'button' || v === 'submit' || v === 'reset';
// component prop: { type: ButtonType } - invalid literals never compile Prevention
- Type button props as `'button' | 'submit' | 'reset'` in your component library
- Express dynamic choices as conditionals with literal branches so the rule (and readers) can resolve them
- Keep the `button`/`submit`/`reset` config flags in sync with your design-system rules
When it happens
Trigger: `<button type="foo" />`; `<button type={foo} />` (dynamic identifier); `<button type={`button${suffix}`} />`; `type={cond ? "button" : "reset"}` with `reset: false`; `createElement("button", { type: "foo" })`.
Common situations: Type driven by a variable or config map; template literals built at runtime; teams restricting submit buttons in form-heavy codebases via the config flags.
Related errors
- `button` elements must have an explicit `type` attribute.
- `checked` should be used with either `onChange` or `readOnly
- Use either `checked` or `defaultChecked`, but not both.
- Component definition is missing display name.
- Invalid handler name: {handler_name}
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/aa89c48959bd02e3.
Report an issue: GitHub.