Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
Ask Question
I’m new in TypeScript and trying to use it with Vue 3 composition API and provide / inject.
Let's say in parent component
A
I have something like this:
// Parent component A
import { provide, ref } from 'vue';
import ScoreType from "@/types/Score";
setup() {
const score = ref<ScoreType[]>([]);
const updateScore = (val: ScoreType) => {
score.value.push(val);
provide('update_score', updateScore);
...and then want to inject updateScore
function in child component B
to be able to update values in parent component A
(this is what docs recommend). Unfortunately, I get a TS error Object is of type 'unknown'
// Child component B
import { inject } from 'vue';
setup() {
const updateScore = inject('update_score');
const checkAnswer = (val: string) => {
updateScore({ /* ScoreType object */ }); // → Object is of type 'unknown'.
What should I do to fix the TypeScript error? I couldn't find any examples about injecting update functions in TS.
Let's firstly declare a type for our updateScore()
function
// @/types/score.ts
export type ScoreType = { points: number };
export type UpdateScoreFunction = (val: ScoreType) => void;
Now we need to declare an InjectionKey
which will hold the type information of our provided/injected variable (function in this case). More about it in Vue docs
Let's make a separate folder to store our keys and to keep the things organized:
// @/symbols/score.ts
import { InjectionKey } from "vue";
import { UpdateScoreFunction } from "@/types/score";
export const updateScoreKey: InjectionKey<UpdateScoreFunction> = Symbol("updateScore");
In our parent component (A)
:
<script lang="ts">
import { defineComponent, provide, ref } from "vue";
import { ScoreType, UpdateScoreFunction } from "@/types/score";
import { updateScoreKey } from "@/symbols/score";
export default defineComponent({
setup() {
const score = ref<ScoreType[]>([]);
// Actually, adding ': UpdateScoreFunction' is optional
const updateScore: UpdateScoreFunction = function (val: ScoreType) {
score.value.push(val);
// Replace the string with InjectionKey
provide(updateScoreKey, updateScore);
// ...
</script>
In our child component (B)
:
<script lang="ts">
import { defineComponent, inject } from "vue";
import { updateScoreKey } from "@/symbols/score";
export default defineComponent({
setup() {
// Replace the string with InjectionKey
const updateScore = inject(updateScoreKey);
// In case the `updateScoreKey` is not provided by the parent component..
if (updateScore === undefined) {
throw new Error('Failed to inject "updateScore"');
const checkAnswer = (val: string) => {
// ...
// The error is gone
updateScore({
points: Math.floor(Math.random() * 100),
// ...
</script>
Working example provided here: codesandbox.io/s/so-provide-inject
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.