'How to type vue instance out of `defineComponent()` in vue 3?

As you know, as of Vue 3, component could be written in TypeScript:

/// modal.vue

<template>
  <div class="modal"></div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "Modal",
  props: {
    foo: String,
    bar: String
  },
  mounted() {
    this.$props.foo // how to type `this` out of this context?
  }
});
</script>

My question is how can I type the vue instance out of the defineComponent function?

/// another ts file.
let modal:???; // what the `???` should be?

modal.$props.foo // infer `$props.foo` correctly


Solution 1:[1]

The "simple" answer I was going to give was to use ReturnType<typeof defineComponent> however that doesn't carry any of the type information. As I started to look at how ReturnType could be used with a generic method I fell down stackoverflow rabbit hole where these seemed like something to explore

However after looking at it, vue has an exported type ComponentPublicInstance that can be used fairly easily. ComponentPublicInstance also has handful of different generic parameters.

import { ComponentPublicInstance } from 'vue';

let instance: ComponentPublicInstance<{ prop: string }, { value: string }>;

Solution 2:[2]

Use the TypeScript's built-in InstanceType utility to extract its instance type

import Modal from './modal.vue'

type ModalInstance = InstanceType<typeof Modal>

type Foo = ModalInstance['$props']['foo']

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David Driscoll
Solution 2