TypeScript 在 Vue2 中的类型声明问题

2022-02-25 11:16:38 浏览数 (1)

0x00 hello world

最近在一个新项目中,尝试了vue2 typescript的组合,碰到一个问题,在data属性中,我怎么声明一个变量的类型。

代码语言:html复制
<script lang="ts">
import Vue from "vue";

interface Foo {
  a: string;
  b: string;
}

export default Vue.extend({
  data: function () {
    return {
      bar: {}, //怎么优雅的告诉编译器他的类型
      bars: [],
    };
  },
});
</script>

在上面的代码里面, barbars的类型分别是:

1.PNG1.PNG

0x01 应急方案

代码语言:html复制
<script lang="ts">
import Vue from "vue";

interface Foo {
  a: string;
  b: string;
}

export default Vue.extend({
  data: function () {
    return {
      bar: {}, //怎么优雅的告诉编译器他的类型
      bars: [],
    };
  },
  methods: {
    abc: function () {
      (this.bar as Foo).a = "";
      (this.bars as Foo[]).push({ a: "", b: "" });
    },
  },
});
</script>

一开始,我能想到的方法就是简单粗暴的强制类型转换,但是随着项目中代码越来越多,我发现这一点也不优雅,非常容易出错。我必须得想个更好更优雅的方法。

0x02 数组类型

如果变量是一个数组类型,很容易就想到这么写:

代码语言:html复制
<script lang="ts">
import Vue from "vue";

interface Foo {
  a: string;
  b: string;
}

export default Vue.extend({
  data: function () {
    return {
      bar: {}, //怎么优雅的告诉编译器他的类型
      bars: new Array<Foo>(),
    };
  },
});
</script>

事实上,这确实很好,很优雅,可是非数据类型就没办法了。

0x03 非数组类型

代码语言:html复制
<script lang="ts">
import Vue from "vue";

interface Foo {
  a: string;
  b: string;
}

export default Vue.extend({
  data: function () {
    return {
      bar: undefined as Foo | undefined, 
      bars: new Array<Foo>(),
    };
  },
  methods: {
    abc: function () {
      if (this.bar) {
        this.bar.a = "";
      }
    },
  },
});
</script>

这样,只要在函数里面,把所有用到的变量都放在一个if里面,保证他不是undefined就可以正常使用了。

0x04 统一写法

代码语言:html复制
<script lang="ts">
import Vue from "vue";

interface Foo {
  a: string;
  b: string;
}

export default Vue.extend({
  data: function () {
    return {
      bar: undefined as Foo | undefined, 
      bars: [] as Foo[],
    };
  },
  methods: {
    abc: function () {
      if (this.bar) {
        this.bar.a = "";
      }
    },
  },
});
</script>

数组类型也通过[] as Foo[]的写法,使得数组和非数组在写法上统一了,更优雅了一点。

0x05 类型扩展

还有个常见的问题,一般来说,Foo类型是接口那边定义的类型,定义了接口返回的数据类型,但是在编码过程中,对接口返回的数据进行处理后,需要保存处理后的信息到变量中,如何在不修改Foo类型的定义的前提下,对Foo类型进行扩展呢?

代码语言:html复制
<script lang="ts">
import Vue from "vue";

interface Foo {
  a: string;
  b: string;
}

interface FooEx extends Foo {
  ab: string;//a b
}

export default Vue.extend({
  data: function () {
    return {
      bar: undefined as FooEx | undefined,
      bars: [] as FooEx[],
    };
  },
  methods: {
    abc: function () {
      if (this.bar) {
        const foo = { a: "", b: "" }; //假设这个数据是接口返回的
        const foos = [foo]; //假设这个数据是接口返回的

        this.bar = { ...foo, ab: foo.a   foo.b };
        this.bars = foos.map((item) => {
          return { ...item, ab: item.a   item.b };
        });
      }
    },
  },
});
</script>

最后

后来我在网上搜索了下这个问题的解决方案,好像也是这么搞的,看来是我孤陋寡闻了,像个憨憨一样花了一晚上时间重构代码。

0 人点赞