Просмотр исходного кода

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

close #9587 
close #10676
yangxiuxiu 2 лет назад
Родитель
Сommit
0cef65cee4

+ 20 - 0
packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineModel.spec.ts.snap

@@ -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'
 

+ 20 - 0
packages/compiler-sfc/__tests__/compileScript/defineModel.spec.ts

@@ -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,
+    })
+  })
 })

+ 11 - 7
packages/compiler-sfc/src/script/defineModel.ts

@@ -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 =