})"
`;
+
+exports[`defineModel() > w/ types, production mode, boolean + multiple types 1`] = `
+"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+ props: {
+ "modelValue": { type: [Boolean, String, Object] },
+ "modelModifiers": {},
+ },
+ emits: ["update:modelValue"],
+ setup(__props, { expose: __expose }) {
+ __expose();
+
+ const modelValue = _useModel<boolean | string | {}>(__props, "modelValue")
+
+return { modelValue }
+}
+
+})"
+`;
+
+exports[`defineModel() > w/ types, production mode, function + runtime opts + multiple types 1`] = `
+"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+ props: {
+ "modelValue": { type: [Number, Function], ...{ default: () => 1 } },
+ "modelModifiers": {},
+ },
+ emits: ["update:modelValue"],
+ setup(__props, { expose: __expose }) {
+ __expose();
+
+ const modelValue = _useModel<number | (() => number)>(__props, "modelValue")
+
+return { modelValue }
+}
+
+})"
+`;
})
})
+ test('w/ types, production mode, boolean + multiple types', () => {
+ const { content } = compile(
+ `
+ <script setup lang="ts">
+ const modelValue = defineModel<boolean | string | {}>()
+ </script>
+ `,
+ { isProd: true },
+ )
+ assertCode(content)
+ expect(content).toMatch('"modelValue": { type: [Boolean, String, Object] }')
+ })
+
+ test('w/ types, production mode, function + runtime opts + multiple types', () => {
+ const { content } = compile(
+ `
+ <script setup lang="ts">
+ const modelValue = defineModel<number | (() => number)>({ default: () => 1 })
+ </script>
+ `,
+ { isProd: true },
+ )
+ assertCode(content)
+ expect(content).toMatch(
+ '"modelValue": { type: [Number, Function], ...{ default: () => 1 } }',
+ )
+ })
+
test('get / set transformers', () => {
const { content } = compile(
`
import type { LVal, Node, TSType } from '@babel/types'
import type { ScriptCompileContext } from './context'
import { inferRuntimeType } from './resolveType'
-import {
- UNKNOWN_TYPE,
- concatStrings,
- isCallOf,
- toRuntimeTypeString,
-} from './utils'
+import { UNKNOWN_TYPE, isCallOf, toRuntimeTypeString } from './utils'
import { BindingTypes, unwrapTSNode } from '@vue/compiler-dom'
export const DEFINE_MODEL = 'defineModel'
const isProd = !!ctx.options.isProd
let modelPropsDecl = ''
- for (const [name, { type, options }] of Object.entries(ctx.modelDecls)) {
+ for (const [name, { type, options: runtimeOptions }] of Object.entries(
+ ctx.modelDecls,
+ )) {
let skipCheck = false
-
+ let codegenOptions = ``
let runtimeTypes = type && inferRuntimeType(ctx, type)
if (runtimeTypes) {
const hasBoolean = runtimeTypes.includes('Boolean')
+ const hasFunction = runtimeTypes.includes('Function')
const hasUnknownType = runtimeTypes.includes(UNKNOWN_TYPE)
- if (isProd || hasUnknownType) {
- runtimeTypes = runtimeTypes.filter(
- t =>
- t === 'Boolean' ||
- (hasBoolean && t === 'String') ||
- (t === 'Function' && options),
- )
+ if (hasUnknownType) {
+ if (hasBoolean || hasFunction) {
+ runtimeTypes = runtimeTypes.filter(t => t !== UNKNOWN_TYPE)
+ skipCheck = true
+ } else {
+ runtimeTypes = ['null']
+ }
+ }
- skipCheck = !isProd && hasUnknownType && runtimeTypes.length > 0
+ if (!isProd) {
+ codegenOptions =
+ `type: ${toRuntimeTypeString(runtimeTypes)}` +
+ (skipCheck ? ', skipCheck: true' : '')
+ } else if (hasBoolean || (runtimeOptions && hasFunction)) {
+ // preserve types if contains boolean, or
+ // function w/ runtime options that may contain default
+ codegenOptions = `type: ${toRuntimeTypeString(runtimeTypes)}`
+ } else {
+ // able to drop types in production
}
}
- let runtimeType =
- (runtimeTypes &&
- runtimeTypes.length > 0 &&
- toRuntimeTypeString(runtimeTypes)) ||
- undefined
-
- const codegenOptions = concatStrings([
- runtimeType && `type: ${runtimeType}`,
- skipCheck && 'skipCheck: true',
- ])
-
let decl: string
- if (runtimeType && options) {
+ if (codegenOptions && runtimeOptions) {
decl = ctx.isTS
- ? `{ ${codegenOptions}, ...${options} }`
- : `Object.assign({ ${codegenOptions} }, ${options})`
+ ? `{ ${codegenOptions}, ...${runtimeOptions} }`
+ : `Object.assign({ ${codegenOptions} }, ${runtimeOptions})`
+ } else if (codegenOptions) {
+ decl = `{ ${codegenOptions} }`
+ } else if (runtimeOptions) {
+ decl = runtimeOptions
} else {
- decl = options || (runtimeType ? `{ ${codegenOptions} }` : '{}')
+ decl = `{}`
}
modelPropsDecl += `\n ${JSON.stringify(name)}: ${decl},`