expose and ts types
Vue version
^3.2.39
Link to minimal reproduction
Steps to reproduce
请使用 VSCode 打开
What is expected?
- 使用
setup
函数必须return
expose
的方法才能使 ts 的类型检测通过 - 如果使用
render
或者tsx
的方式,无法显视的return
, ts 类型检查就找不到expose
的属性
What is actually happening?
expose() 和 renturn {}
System Info
System:
OS: macOS 12.5.1
CPU: (8) arm64 Apple M1 Pro
Memory: 5.17 GB / 32.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.16.0 - ~/.nvm/versions/node/v16.16.0/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 8.11.0 - ~/.nvm/versions/node/v16.16.0/bin/npm
Browsers:
Chrome: 105.0.5195.102
Safari: 15.6.1
npmPackages:
vue: ^3.2.37 => 3.2.39
Any additional comments?
No response
use render
property.
render by h
fn
<script lang="ts">
import { defineComponent, h } from "vue";
export default defineComponent({
name: "HelloWorld",
setup() {
const msg = () => {
console.log("msg");
};
return { msg };
},
render() {
return h("div", "hello");
},
});
</script>
render by jsx . add @vitejs/plugin-vue-jsx
and set lang is tsx
<script lang="tsx">
import { defineComponent } from "vue";
export default defineComponent({
name: "HelloWorld",
setup() {
const msg = () => {
console.log("msg");
};
return { msg };
},
render() {
return <div>HelloWorld</div>;
},
});
</script>
InstanceType
tool would expose many properties that you don't need.
or you can create a type to describe Comp instance instead of depend on InstanceType
tool.
type CompInst = {
msg: () => void;
}
in component
// Comp.vue
<script lang="tsx">
import { defineComponent } from "vue";
import { CompInst } from "./type.ts";
export default defineComponent({
name: "Comp",
setup() {
const exposeObj: CompInst = {
// type hint !
msg: () => console.log("msg");
}
return {
...exposeObj
};
},
render() {
return <div>HelloWorld</div>;
},
});
</script>
use
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import Comp from './Comp.vue';
import { CompInst } from "./type.ts";
const compRef = ref<CompInst | null>(null);
onMounted(() => {
// type hint ! and doesn't have any properties that you don't want to expose.
compRef.value?.msg();
});
</script>
<template>
<div>
<Comp ref="compRef" />
</div>
</template>
why not this
<script lang="ts">
import { defineComponent, h } from "vue";
export default defineComponent({
name: "HelloWorld",
setup(_props, { expose }) {
const msg = () => {
console.log("msg");
};
expose({ msg })
return () => (
h("div", "hello");
)
});
</script>
don't need return { msg }
, use expose
can auto mount component Instance.
i have a try, and it can't get type hint from ts by InstanceType<typeof HelloWorld>
, maybe it is a type bug for vue
I used tsx files got the same problem.
// Demo.tsx
import { defineComponent} from "vue";
export default defineComponent({
name: "HelloWorld",
setup(_props, { expose }) {
const msg = () => {
console.log("msg");
};
expose({ msg })
return () => (<div>xxx</div>)
});
// app.tsx
import { defineComponent, onMounted } from 'vue'
import Demo from './Demo'
export default defineComponent({
setup (props) {
const el = ref<InstanceType<typeof Demo>>()
onMounted(() => {
console.log(el.value)
el.value?.msg // Uncaught TypeError: t.value.msg is undefined
})
return () => <Demo ref={el}></Demo>
}
})
https://github.com/vuejs/composition-api/issues/966
Is this the wrong type of vue3?