【问题标题】:TypeScript / Vue 3: Injecting mutating function causes TypeScript error "Object is of type 'unknown'"TypeScript / Vue 3:注入变异函数会导致 TypeScript 错误“对象属于‘未知’类型”
【发布时间】:2021-06-27 09:20:34
【问题描述】:

我是 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 中注入更新函数的示例。

【问题讨论】:

    标签: typescript vuejs3 inject vue-composition-api mutating-function


    【解决方案1】:

    让我们首先为 updateScore() 函数声明一个类型

    // @/types/score.ts
    export type ScoreType = { points: number };
    
    export type UpdateScoreFunction = (val: ScoreType) => void;
    

    现在我们需要声明一个InjectionKey,它将保存我们提供/注入的变量(在本例中为函数)的类型信息。更多信息请关注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

    【讨论】:

    • 谢谢,它有效。但是为什么我们必须处理注入函数“未定义”的可能性呢?我无法想象父母(在我的应用程序中)没有注入功能的情况。它是否与组合 API 以及从“多个部分”组合组件有关?
    • 如果你从父组件中删除provide(updateScoreKey, updateScore);,它将是undefined,因为没有任何东西可以注入到子组件中。如果不想处理,可以给子组件中的inject()函数传递第二个参数,指定默认值:const updateScore = inject(updateScoreKey, function() { ... });
    猜你喜欢
    • 2021-09-18
    • 2021-07-17
    • 1970-01-01
    • 2021-07-02
    • 2022-12-14
    • 2021-04-19
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多