【问题标题】:How can I catch typescript type errors in a Vue component's data?如何在 Vue 组件的数据中捕获 typescript 类型错误?
【发布时间】:2020-12-09 09:40:50
【问题描述】:

我最近开始使用 Nuxt-ts 和 Vue 2 在 Typescript 中进行开发。我试图避免使用 class-style components 编写应用程序,所以我使用了以下解决方案。

我在名为/types 的文件夹中声明我的接口。如果我想在 Vue 组件的data 中声明一个type,我会导入该类型,然后在组件中使用它。

// types/Fruit.ts

export interface Fruit {
  name: string,
  color: string,
  taste: string
}


// components/FruitComponent.vue

<script lang="ts">

import Vue from 'vue'
import { Fruit } from '@/types/fruits'

export default Vue.extend({
  name: 'FruitComponent',
  data() {
    return {
      fruit: {
        name: 'apple',
        color: 'red',
        taste: 'delicious',
        wrongParameter: 'this should be an error',
      } as Fruit
    }
  }
})

</script>

问题是,编译器和可视化代码编辑器不会捕捉到如上所示的错误。

我预计会出现类似于 Object literal wrongParameter is not assignet to type 'Fruit' 的错误。

我应该如何正确地捕捉这种类型的错误?

【问题讨论】:

    标签: typescript vue.js vuejs2 nuxt.js


    【解决方案1】:

    我不了解 Vue,但我绝对完全确定没有办法做到这一点。

    所有类型在编译过程中只存在,所有接口、类型别名、函数重载、联合或任何与打字稿相关的东西,基本上任何存在于打字稿但不存在于javascript中的东西在编译后完全消失了,不能在运行时以任何方式使用。这意味着没有任何try...catch 块可以捕获打字稿错误。 typescript 的重点是提供 compile-time 类型检查。

    您的代码中也没有要捕获的错误。如果你没有写as Fruit,那么打字稿编译器会认为这个代码是错误的,并向你显示你的代码可能是错误的消息。但是当您编写as Fruit 时,您实际上是在告诉编译器“我知道这个对象不是您所期望的,但我确信它与Fruit 兼容。即使它不兼容,我也完全确定一切都会是很好,没有代码会中断,所以不要检查这个对象并假装它是Fruit,即使它不是”。现在你的问题是确保一切都很好,如果出现问题,打字稿也无济于事。

    Typescript 类型系统不像 Java 或 C++ 之类的,它不能保证在运行时一切都会好起来,它只是防止你犯愚蠢的错误,而这些错误可以通过查看代码来避免,并让你编写代码通过在 IDE 中提供类型提示来更快。如果你看一下 typescript 目标,或者更具体地说,non-goals,你会看到第五个

    非目标 5:在程序中添加或依赖运行时类型信息,或根据类型系统的结果发出不同的代码。相反,鼓励不需要运行时元数据的编程模式。

    这基本上意味着我刚刚在上面写的:打字稿不能保证在运行时一切都会好起来。就像您编写以下代码一样:

    interface ApiResponse {
      foo: {
        bar: string
      }
    }
    
    fetch('http://myapi.com')
      .then<ApiResponse>(res => res.json())
      .then(data => console.log(data.foo.bar))
    

    Typescript 不能保证data 确实有属性foo 有属性bar,你有责任检查它。例如,如果 API 发送了一个空对象,那么res.json() 将返回一个空对象,因此data 将是一个空对象,data.foo.bar 将生成一个错误,因为foo 未定义并且您无法读取未定义的属性bar。 Typescript 在这里帮不了你

    【讨论】:

    • @maikelinhas,是的,这实际上是它应该如何工作的。当您需要对某些特定对象进行跳过类型验证时,您只编写类型断言 (as ...),这通常很有用,但通常您希望避免它。在这种情况下,这个断言当然是完全没有必要的
    • 非常感谢!!我删除了我之前的评论,因为它有点混乱,并在我的问题中包含了建议的解决方案。
    【解决方案2】:

    试试这个:

    <script lang="ts">
    import { Component, Prop, Vue,Watch } from 'vue-property-decorator';  
    import { Fruit } from '@/types/fruits'
      
    @Component({
      name: 'FruitComponent', 
      components: { 
      }
    } )
    export default class FruitComponent extends Vue { 
    
    @Prop(  {required: true, type : Object} ) fruit1 !: Fruit ;
    
    fruit2 : Fruit  = { name: 'apple',
            color: 'red',
            taste: 'delicious',
            wrongParameter: 'this should be an error'};//this create an error
     
     
      mounted(){}
    }
    </script>
    

    【讨论】:

      猜你喜欢
      • 2017-10-15
      • 1970-01-01
      • 2021-11-15
      • 2020-06-16
      • 2019-12-08
      • 1970-01-01
      • 2019-05-15
      • 2019-05-17
      • 1970-01-01
      相关资源
      最近更新 更多