fix(compiler-sfc): fix defineModel coercion for boolean + string union types (#9603)

close #9587 
close #10676
This commit is contained in:
yangxiuxiu 2024-04-15 21:18:59 +08:00 committed by GitHub
parent 67722ba23b
commit 0cef65cee4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 51 additions and 7 deletions

View File

@ -103,6 +103,26 @@ return { modelValue }
})"
`;
exports[`defineModel() > w/ Boolean And Function types, production mode 1`] = `
"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'
export default /*#__PURE__*/_defineComponent({
props: {
"modelValue": { type: [Boolean, String] },
"modelModifiers": {},
},
emits: ["update:modelValue"],
setup(__props, { expose: __expose }) {
__expose();
const modelValue = _useModel<boolean | string>(__props, "modelValue")
return { modelValue }
}
})"
`;
exports[`defineModel() > w/ array props 1`] = `
"import { useModel as _useModel, mergeModels as _mergeModels } from 'vue'

View File

@ -221,4 +221,24 @@ describe('defineModel()', () => {
assertCode(content)
expect(content).toMatch(`set: (v) => { return v + __props.x }`)
})
test('w/ Boolean And Function types, production mode', () => {
const { content, bindings } = compile(
`
<script setup lang="ts">
const modelValue = defineModel<boolean | string>()
</script>
`,
{ isProd: true },
)
assertCode(content)
expect(content).toMatch('"modelValue": { type: [Boolean, String] }')
expect(content).toMatch('emits: ["update:modelValue"]')
expect(content).toMatch(
`const modelValue = _useModel<boolean | string>(__props, "modelValue")`,
)
expect(bindings).toStrictEqual({
modelValue: BindingTypes.SETUP_REF,
})
})
})

View File

@ -129,15 +129,19 @@ export function genModelProps(ctx: ScriptCompileContext) {
let runtimeTypes = type && inferRuntimeType(ctx, type)
if (runtimeTypes) {
const hasBoolean = runtimeTypes.includes('Boolean')
const hasUnknownType = runtimeTypes.includes(UNKNOWN_TYPE)
runtimeTypes = runtimeTypes.filter(el => {
if (el === UNKNOWN_TYPE) return false
return isProd
? el === 'Boolean' || (el === 'Function' && options)
: true
})
skipCheck = !isProd && hasUnknownType && runtimeTypes.length > 0
if (isProd || hasUnknownType) {
runtimeTypes = runtimeTypes.filter(
t =>
t === 'Boolean' ||
(hasBoolean && t === 'String') ||
(t === 'Function' && options),
)
skipCheck = !isProd && hasUnknownType && runtimeTypes.length > 0
}
}
let runtimeType =