正文
Vue3里使用了
type form = InstanceType<typeof Form>
语法。
我们观察.vue文件可以知道都是export default defineComponent,
defineComponent的文档在https://vuejs.org/api/general.html#definecomponent
可知道:
defineComponent是为了帮助ts进行类型推断的函数,
参数是一个组件选项对象,而返回值也是相同的对象。
本质上仅用于类型推断,无任何其他操作,
然而返回类型携带了一个虚拟的构造函数,
我们没法将它用于new,但是可以通过它来推导构造出一个vue实例来做类型推断,
我们观察它的类型声明可以知道:
export declare type DefineComponent<PropsOrPropOptions = {}, RawBindings = {}, D = {}, C extends ComputedOptions = ComputedOptions, M extends MethodOptions = MethodOptions, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record<string, any>, EE extends string = string, PP = PublicProps, Props = Readonly<ExtractPropTypes<PropsOrPropOptions>>, Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>> = ComponentPublicInstanceConstructor<CreateComponentPublicInstance<Props, RawBindings, D, C, M, Mixin, Extends, E, PP & Props, Defaults, true> & Props> & ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE, Defaults> & PP;
这里忽略大部分泛型,仅观察后边的返回类型可以知道是:
ComponentPublicInstanceConstructor和其他类型的联合,
而我们再点击进去看看可以知道,
declare type ComponentPublicInstanceConstructor<T extends ComponentPublicInstance<Props, RawBindings, D, C, M> = ComponentPublicInstance<any>, Props = any, RawBindings = any, D = any, C extends ComputedOptions = ComputedOptions, M extends MethodOptions = MethodOptions> = {
__isFragment?: never;
__isTeleport?: never;
__isSuspense?: never;
new (...args: any[]): T;
};
这里的ComponentPublicInstanceConstructor是一个存在一个new的构造函数,返回T泛型,
所以我们可以知道如果对一个组件对象进行typeof,
得到的是ComponentPublicInstanceConstructor与其他类型联合的一个联合类型,
因为这个联合类型具有一个虚假的类型声明new (...args: any[]): T;,
所以对其调用InstanceType将会返回一个组件的实例,
InstanceType的作用是返回一个类型中的构造函数的实例类型,
所以全程我们是通过一个组件的对象获取到了他的实际ts推导类型,然后根据推导类型得,到构造函数,再根据构造函数获取到了实例类型,
来做ref推导。
结语
可能存在事实错误,
资料实在太少了...