oxc-project/oxc · error · OxcDiagnostic

`defineProps` has both a type-only emit and an argument.

Error message

`defineProps` has both a type-only emit and an argument.

What it means

Diagnostic from the oxlint rule `vue/valid-define-props` (crates/oxc_linter/src/rules/vue/valid_define_props.rs). The rule delegates each `defineProps` call to the shared helper `check_define_macro_call_expression`; when the call has BOTH a literal type parameter (type-only declaration) and a runtime argument, the helper returns `DefineMacroProblem::HasTypeAndArguments`. Passing both makes the runtime argument win and silently discards the type-only declaration, degrading type inference.

Source

Thrown at crates/oxc_linter/src/rules/vue/valid_define_props.rs:14

use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{
    context::LintContext,
    frameworks::FrameworkOptions,
    rule::Rule,
    utils::{DefineMacroProblem, check_define_macro_call_expression, has_default_exports_property},
};

fn has_type_and_arguments_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("`defineProps` has both a type-only emit and an argument.")
        .with_help("remove the argument for better type inference.")
        .with_label(span)
}

fn called_multiple_times(span: Span, second_span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("`defineProps` has been called multiple times.")
        .with_help("combine all `defineProps` calls into a single `defineProps` call.")
        .with_labels([
            span.label("`defineProps` is called here"),
            second_span.label("`defineProps` is called here too"),
        ])
}

fn events_not_defined(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Props are not defined.")
        .with_help("Define at least one prop in `defineProps`.")
        .with_label(span)
}

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Delete the runtime argument and keep the type-only form: `defineProps<{ msg?: string }>()`.
  2. If you need prop defaults with types, use `withDefaults(defineProps<{ msg?: string }>(), { msg: 'hi' })` instead of a second argument.
  3. If the runtime object is the source of truth, drop the type parameter instead: `defineProps({ msg: String })`.

Example fix

// before
<script setup lang="ts">
defineProps<{ msg?: string }>({ msg: String })
</script>

// after
<script setup lang="ts">
defineProps<{ msg?: string }>()
</script>
Defensive patterns

Strategy: validation

Validate before calling

if (/\bdefineProps\s*<[^>]*>\s*\(\s*\S/.test(src)) {
  throw new Error('defineProps has both a type parameter and a runtime argument — remove one');
}

Prevention

When it happens

Trigger: A `defineProps` call (VueSetup framework option) shaped like `defineProps<{ msg?: string }>({ msg: String })` — i.e. `call.type_arguments` present AND at least one runtime argument. Reported on the whole call span with help 'remove the argument for better type inference.'

Common situations: Migrating a runtime-props component to type-based props and forgetting to delete the old object argument; merging tutorial snippets that use both styles; refactors where a defaults object was pasted next to a newly added type parameter.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/62487c3d7522e61e. Report an issue: GitHub.