TypeScript / Vue 3:注入变异函数导致 TypeScript 错误 "Object is of type 'unknown'"
TypeScript / Vue 3: Injecting mutating function causes TypeScript error "Object is of type 'unknown'"
我是 TypeScript 的新手,正在尝试将它与 Vue 3 组合一起使用 API 并提供/注入。
假设在父组件 A
我有这样的东西:
// 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);
..
}
...然后想在子组件 B
中注入 updateScore
函数,以便能够更新父组件 A
(this is what docs recommend) 中的值。不幸的是,我收到 TS 错误 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'.
}
..
}
我应该如何修复 TypeScript 错误?我找不到任何关于在 TS 中注入更新函数的例子。
让我们首先为我们的 updateScore()
函数声明一个类型
// @/types/score.ts
export type ScoreType = { points: number };
export type UpdateScoreFunction = (val: ScoreType) => void;
现在我们需要声明一个 InjectionKey
来保存我们的 provided/injected 变量(在本例中为函数)的类型信息。更多信息请见 Vue docs
让我们创建一个单独的文件夹来存储我们的密钥并使事情井井有条:
// @/symbols/score.ts
import { InjectionKey } from "vue";
import { UpdateScoreFunction } from "@/types/score";
export const updateScoreKey: InjectionKey<UpdateScoreFunction> = Symbol("updateScore");
在我们的父组件中(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>
在我们的子组件中 (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>
此处提供工作示例:codesandbox.io/s/so-provide-inject
我是 TypeScript 的新手,正在尝试将它与 Vue 3 组合一起使用 API 并提供/注入。
假设在父组件 A
我有这样的东西:
// 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);
..
}
...然后想在子组件 B
中注入 updateScore
函数,以便能够更新父组件 A
(this is what docs recommend) 中的值。不幸的是,我收到 TS 错误 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'.
}
..
}
我应该如何修复 TypeScript 错误?我找不到任何关于在 TS 中注入更新函数的例子。
让我们首先为我们的 updateScore()
函数声明一个类型
// @/types/score.ts
export type ScoreType = { points: number };
export type UpdateScoreFunction = (val: ScoreType) => void;
现在我们需要声明一个 InjectionKey
来保存我们的 provided/injected 变量(在本例中为函数)的类型信息。更多信息请见 Vue docs
让我们创建一个单独的文件夹来存储我们的密钥并使事情井井有条:
// @/symbols/score.ts
import { InjectionKey } from "vue";
import { UpdateScoreFunction } from "@/types/score";
export const updateScoreKey: InjectionKey<UpdateScoreFunction> = Symbol("updateScore");
在我们的父组件中(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>
在我们的子组件中 (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>
此处提供工作示例:codesandbox.io/s/so-provide-inject