Skip to content

Commit d5c6635

Browse files
Added template refs typing instruction (#1022)
* feat: added template refs typing * fix: fixed to non-SFC * fix: removed code block
1 parent 64cbc01 commit d5c6635

File tree

1 file changed

+75
-4
lines changed

1 file changed

+75
-4
lines changed

src/guide/typescript-support.md

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ For developing Vue applications with TypeScript, we strongly recommend using [Vi
9090

9191
[WebStorm](https://www.jetbrains.com/webstorm/) also provides out-of-the-box support for both TypeScript and Vue.
9292

93-
## Defining Vue components
93+
## Defining Vue Components
9494

9595
To let TypeScript properly infer types inside Vue component options, you need to define components with `defineComponent` global method:
9696

@@ -221,10 +221,10 @@ const Component = defineComponent({
221221
// in a computed with a setter, getter needs to be annotated
222222
greetingUppercased: {
223223
get(): string {
224-
return this.greeting.toUpperCase();
224+
return this.greeting.toUpperCase()
225225
},
226226
set(newValue: string) {
227-
this.message = newValue.toUpperCase();
227+
this.message = newValue.toUpperCase()
228228
}
229229
}
230230
}
@@ -298,7 +298,7 @@ const Component = defineComponent({
298298
})
299299
```
300300

301-
### Annotating emits
301+
### Annotating Emits
302302

303303
We can annotate a payload for the emitted event. Also, all non-declared emitted events will throw a type error when called:
304304

@@ -372,6 +372,77 @@ year.value = 2020 // ok!
372372
If the type of the generic is unknown, it's recommended to cast `ref` to `Ref<T>`.
373373
:::
374374

375+
### Typing Template Refs
376+
377+
Sometimes you might need to annotate a template ref for a child component in order to call its public method. For example, we have a `MyModal` child component with a method that opens the modal:
378+
379+
```ts
380+
import { defineComponent, ref } from 'vue'
381+
382+
const MyModal = defineComponent({
383+
setup() {
384+
const isContentShown = ref(false)
385+
const open = () => (isContentShown.value = true)
386+
387+
return {
388+
isContentShown,
389+
open
390+
}
391+
}
392+
})
393+
```
394+
395+
We want to call this method via a template ref from the parent component:
396+
397+
```ts
398+
import { defineComponent, ref } from 'vue'
399+
400+
const MyModal = defineComponent({
401+
setup() {
402+
const isContentShown = ref(false)
403+
const open = () => (isContentShown.value = true)
404+
405+
return {
406+
isContentShown,
407+
open
408+
}
409+
}
410+
})
411+
412+
const app = defineComponent({
413+
components: {
414+
MyModal
415+
},
416+
template: `
417+
<button @click="openModal">Open from parent</button>
418+
<my-modal ref="modal" />
419+
`,
420+
setup() {
421+
const modal = ref()
422+
const openModal = () => {
423+
modal.value.open()
424+
}
425+
426+
return { modal, openModal }
427+
}
428+
})
429+
```
430+
431+
While this will work, there is no type information about `MyModal` and its available methods. To fix this, you should use `InstanceType` when creating a ref:
432+
433+
```ts
434+
setup() {
435+
const modal = ref<InstanceType<typeof MyModal>>()
436+
const openModal = () => {
437+
modal.value?.open()
438+
}
439+
440+
return { modal, openModal }
441+
}
442+
```
443+
444+
Please note that you would also need to use [optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) or any other way to check that `modal.value` is not undefined.
445+
375446
### Typing `reactive`
376447

377448
When typing a `reactive` property, we can use interfaces:

0 commit comments

Comments
 (0)