Skip to content

feat: extend require-default-prop and require-valid-default-prop to check defineModel#3032

Open
seanogdev wants to merge 9 commits intovuejs:masterfrom
seanogdev:definemodel-default
Open

feat: extend require-default-prop and require-valid-default-prop to check defineModel#3032
seanogdev wants to merge 9 commits intovuejs:masterfrom
seanogdev:definemodel-default

Conversation

@seanogdev
Copy link

Closes #2369.

Changes

Extends require-default-prop and require-valid-default-prop to check defineModel calls.

Since defineModel is effectively a prop+emit pair, both rules now enforce the same constraints they apply to defineProps: non-required, non-Boolean props must have a default value, and any provided default must be valid for the declared type.

Tests should validate the change.

@changeset-bot
Copy link

changeset-bot bot commented Feb 24, 2026

🦋 Changeset detected

Latest commit: e03f692

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
eslint-plugin-vue Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Member

@FloEdelmann FloEdelmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late review!

In general the code looks good, but I have a few remarks, see below.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Extends the existing prop-default enforcement rules to also analyze <script setup> defineModel() macro usage, treating models similarly to props for default requirements and default-type validity.

Changes:

  • Add defineModel() support to vue/require-default-prop (missing default detection) and vue/require-valid-default-prop (default value type validation).
  • Expand rule documentation with defineModel() examples.
  • Add test cases covering valid/invalid defineModel() patterns (runtime types and TypeScript generics).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
lib/rules/require-default-prop.js Adds onDefineModelEnter reporting for missing defaults on defineModel() where applicable.
lib/rules/require-valid-default-prop.ts Adds defineModel() default-type validation, including TS-generic type inference via ts-types.
tests/lib/rules/require-default-prop.test.ts Adds valid/invalid defineModel() coverage for missing-default behavior.
tests/lib/rules/require-valid-default-prop.test.ts Adds valid/invalid defineModel() coverage for default-type validation behavior.
docs/rules/require-default-prop.md Documents defineModel() examples for missing-default rule.
docs/rules/require-valid-default-prop.md Documents defineModel() examples for default-type validation rule.
.changeset/lucky-waves-obey.md Adds a patch changeset entry for the new defineModel() support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +222 to +247
onDefineModelEnter(node, model) {
if (model.options && model.options.type === 'ObjectExpression') {
if (
propIsRequired(model.options) ||
propHasDefault(model.options) ||
model.options.properties.some(
(p) =>
p.type === 'Property' &&
utils.getStaticPropertyName(p) === 'type' &&
isValueNodeOfBooleanType(p.value)
)
) {
return
}
context.report({
node: model.options,
messageId: 'missingDefault',
data: { propName: model.name.modelName }
})
} else {
context.report({
node: model.options || node,
messageId: 'missingDefault',
data: { propName: model.name.modelName }
})
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onDefineModelEnter ignores model.typeNode (TypeScript generic) when deciding whether a default is required. This causes false positives for cases like defineModel<boolean>() / defineModel<boolean>({}), where Boolean models should be exempt from the default requirement (same as Boolean props elsewhere in this rule). Consider inferring runtime types from model.typeNode (e.g. via the existing ts-utils inference) and skipping the report when the inferred type is only Boolean (and still honoring required/default when provided).

Copilot uses AI. Check for mistakes.
parser: vueEslintParser,
...languageOptions,
parserOptions: { parser: require.resolve('@typescript-eslint/parser') }
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new defineModel TypeScript valid cases don't include a Boolean-generic scenario (e.g. defineModel<boolean>() or defineModel<boolean>({})). Adding this would guard the rule behavior that Boolean models should not require a default, and would prevent regressions once model.typeNode handling is added/fixed.

Suggested change
}
}
},
{
filename: 'test.vue',
code: `
<script setup lang="ts">
defineModel<boolean>()
</script>
`,
languageOptions: {
parser: vueEslintParser,
...languageOptions,
parserOptions: { parser: require.resolve('@typescript-eslint/parser') }
}
},
{
filename: 'test.vue',
code: `
<script setup lang="ts">
defineModel<boolean>({})
</script>
`,
languageOptions: {
parser: vueEslintParser,
...languageOptions,
parserOptions: { parser: require.resolve('@typescript-eslint/parser') }
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extend vue/require-valid-default-prop to check inside defineModel

3 participants