Subscribe on changes!

使用 defineModel 传递类型之后编译结果不一致

avatar
Jun 20th 2023

Vue version

3.3.4

Link to minimal reproduction

https://github.com/FightingDesign/fighting-design

Steps to reproduce

pnpm i

pnpm build

查看 dist\es\radio-group\src\index.js

What is expected?

打包之后的类型和 props 类型一致

What is actually happening?

在传递 ts 类型和不传递的时候,编译出来的结果不一致

传递类型

import type { PropType } from 'vue'

type RadioModelValue = string | number | boolean

const prop = defineProps({
  modelValue: {
    type: [String, Number, Boolean] as PropType<RadioModelValue>,
    default: null,
  },
})

const modelValue = defineModel<RadioModelValue>({
  required: true,
  default: null,
})

// 编译结果为:

// modelValue: { type: Boolean, required: !0, default: null }

不传递类型

import type { PropType } from 'vue'

type RadioModelValue = string | number | boolean

const prop = defineProps({
  modelValue: {
    type: [String, Number, Boolean] as PropType<RadioModelValue>,
    default: null,
  },
})

const modelValue = defineModel({
  required: true,
  default: null,
})

// 编译结果为:

// modelValue: { required: !0, default: null }

为什么传递 ts 类型进去之后就会多编译出 type: Boolean

我希望可以编译出和 prop.modelValue 一样的类型 [String, Number, Boolean]

我尝试直接将 type 传递进去:

const modelValue = defineModel<RadioModelValue>({
  required: true,
  default: null,
  type: [String, Number, Boolean],
})

// 编译结果为:

//  modelValue: { type: Boolean, required: !0, default: null, type: [String, Number, Boolean] }

虽然后者 type 会覆盖前面的 type,但这样的编译结果显然是不好的

System Info

windows11

"vue": "^3.3.4"
"vitepress": "1.0.0-beta.3"
"vite": "^4.3.9"
"vitest": "^0.32.2"
"vue-tsc": "^1.8.0"

Any additional comments?

错误的类型会导致警告信息提示:

af7ee02edae1ee38fec760049a7fcef
avatar
Jun 21st 2023

It's by design.

Like defineProps, Vue need Boolean type for runtime usage. So either add runtime type property type: [String, Number, Boolean] as PropType<RadioModelValue>, or add a type generic defineModel<RadioModelValue>()


In production mode, runtime type checking will be skipped, so only Boolean is necessary and the others are useless without runtime type checking.

avatar
Jun 27th 2023

You shouldn't use generics and argument together