在Vue 3中,为什么defineComponent声明的返回类型与返回对象的结构不匹配

问题描述 投票:0回答:1

我对 Typescript 不太有经验,但我的印象是,如果声明的类型正确,它们应该与它们所描述的对象的运行时结构相匹配。我正在重构 Vue 代码库(并将其迁移到打字稿),其中 Vue 组件定义在从 SFC 导入后被修改。

原始代码期望导入的组件定义具有一定的结构(具体来说具有“props”字段),它确实如此。但是,将其移至打字稿并启用类型检查后,导入的组件定义的类型为 DefineComponent -- https://github.com/vuejs/core/blob/574c3e63bbb764c82fd7228eac979bb3e7fa731d/packages/runtime-core/src/apiDefineComponent.ts #L44 具有完全不同的结构并且没有“props”字段。

我的问题是为什么会出现这种差异。

我们可以通过创建 vue 3 脚手架项目来观察有限环境中的行为 - https://cli.vuejs.org/guide/creating-a-project.html然后将 main.ts 修改为以下内容:

import { createApp, defineComponent } from 'vue'
const comp = defineComponent({props: ['msg'], render:()=>"HELLO WORLD"})
console.log(comp)
new comp()

createApp(comp).mount('#app')

这段代码编译正确,具体来说,

comp
变量可以用作构造函数(
defineComponent
的类型声明表明它是)。但是,在运行时,代码会失败,因为
comp
指向

{
   "props": ["msg"],
   "render": () => () => "HELLO WORLD"
}

我期望运行时

comp
的值与声明的类型兼容,但事实并非如此。 即使组件是导入的 SFC 并且未内联定义,此行为也是相同的。

typescript vuejs3
1个回答
0
投票

再苦苦挣扎之后更新:

defineComponent
的返回类型需要为
DefineComponent
类型,因为它可以用作 TSX 基于值的元素 - https://www.typescriptlang.org/docs/handbook/jsx.html 。上面引用的 tsx 文档指定了如何对元素进行类型检查。即,元素名称必须在 ts 范围内,并且必须是其签名与提供给 tsx 元素的属性匹配的构造函数。因此,在这种情况下,让结果的类型与选项对象(结果实际上是在运行时的)兼容将不起作用。

© www.soinside.com 2019 - 2024. All rights reserved.