{"record":{"id":"8a3d319d1fb2212b","repo":"oxc-project/oxc","slug":"props-are-defined-in-both-defineprops-and-expor","errorCode":null,"errorMessage":"Props are defined in both `defineProps` and `export default {}`.","messagePattern":"Props are defined in both `defineProps` and `export default (.+?)`\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/vue/valid_define_props.rs","lineNumber":41,"sourceCode":"            span.label(\"`defineProps` is called here\"),\n            second_span.label(\"`defineProps` is called here too\"),\n        ])\n}\n\nfn events_not_defined(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Props are not defined.\")\n        .with_help(\"Define at least one prop in `defineProps`.\")\n        .with_label(span)\n}\n\nfn referencing_locally(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"`defineProps` is referencing locally declared variables.\")\n        .with_help(\"inline the variable or import it from another module.\")\n        .with_label(span)\n}\n\nfn define_in_both(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Props are defined in both `defineProps` and `export default {}`.\")\n        .with_help(\"Remove `export default`.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct ValidDefineProps;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Enforce valid usage of the `defineProps` compiler macro in Vue.\n    ///\n    /// This rule reports `defineProps` compiler macros in the following cases:\n    ///\n    /// - `defineProps` is referencing locally declared variables.\n    /// - `defineProps` has both a literal type and an argument. e.g. `defineProps<{ /*props*/ }>({ /*props*/ })`\n    /// - `defineProps` has been called multiple times.\n    /// - Props are defined in both `defineProps` and `export default {}`.","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/vue/valid_define_props.rs#L23-L59","documentation":"Diagnostic from the oxlint rule `vue/valid-define-props`. Before scanning calls, the rule computes `has_other_script_emits = has_default_exports_property(&ctx.other_file_hosts(), \"props\")` — true when a sibling plain `<script>` block exports a default object containing a `props` property. If `defineProps` also declares props in `<script setup>`, the helper returns `DefineMacroProblem::DefineInBoth`. Declaring props twice makes the two declarations compete and the compiled component's props become ambiguous.","triggerScenarios":"A .vue file (VueSetup) that has BOTH `<script> export default { props: { msg: String } } </script>` AND a `defineProps({ count: Number })` in `<script setup>`. Any `defineProps` call with a declaration (argument or type parameter) while the sibling `export default {}` has a `props` key triggers it; the diagnostic span is the `defineProps` call.","commonSituations":"Partial migration from Options API where `export default { props }` was left behind after adding `defineProps`; mixing both styles in one file because examples were combined; tooling that injects `defineProps` into files that still declare props the old way.","solutions":["Remove the `export default {}` from the plain `<script>` block (help text: 'Remove `export default`') and keep props solely in `defineProps`.","Alternatively keep `export default { props: {...} }` and delete the `defineProps` call — but never both.","After removing, re-run lint: the companion 'Props are not defined' diagnostic also disappears only if one declaration remains."],"exampleFix":"// before\n<script>\nexport default { props: { msg: String } }\n</script>\n<script setup>\ndefineProps({ count: Number })\n</script>\n\n// after\n<script setup>\ndefineProps({ msg: String, count: Number })\n</script>","handlingStrategy":"validation","validationCode":"const bothWays =\n  /export\\s+default\\s*\\{[\\s\\S]*?\\bprops\\s*:/.test(src) &&\n  /\\bdefineProps\\s*[(<]/.test(setup);\nif (bothWays) {\n  throw new Error('Props declared both in export default {} and defineProps — remove one');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Finish Options API → script setup migrations: remove export default { props } once defineProps exists.","Lint .vue files with vue/valid-define-props in CI to catch half-migrated files."],"tags":["vue","script-setup","compiler-macro","defineprops","options-api","lint","duplicate-declaration"],"backgroundTag":"vue-script-setup-macro-misuse","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}