0%

typescript-array-literal-type

问题提出

今天刚到公司,前端组的小美找到我,说有一个数组类型搞不定,让我帮忙看一下,简单来说就是小美调用api后返回的数据无法赋值给下面这个类型。

先看一下这个返回值类型定义,注意这里的students是一个数组字面量,而不是普通的数组,数组中的元素是一个对象,对象中有nameage两个属性。

1
2
3
4
5
6
7
8
interface response {
students: [
{
name: string;
age: number;
}
];
}

下面是小美的API返回的数据,注意这个返回值是一个数组,而非数组字面量。

1
2
3
4
5
6
7
8
9
10
11
12
const data: response = {
students: [
{
name: 'Philip',
age: 18,
},
{
name: 'Tom',
age: 20,
},
],
};

返回值中students数组中的元素个数是不对的,因为students的类型定义是一个元素的数组字面量,但是返回值中的students却包含两个元素(这相当于把students当作数组类型来使用,而不是当作数组字面量来使用)。所以TS会给出如下提示:

1
2
xxx is not assignable to type [{ name: string; age: number; }]
Source has 2 element(s) but target allows only 1

解决办法

为了避免上面对的错误提示,我们可以使用Array类型来定义students

1
2
3
4
5
6
interface response {
students: Array<{
name: string;
age: number;
}>;
}

如此定义,则students是一个数组,不再是数组字面量,这样就可以包含任意个元素了。当然也可以使用[]来定义students

1
2
3
4
5
6
interface response {
students: {
name: string;
age: number;
}[];
}

这种方法和上面的方法是等价的。这时,我们再使用上面的data就不会报错了。

1
2
3
4
5
6
7
8
9
10
11
12
const data: response = {
students: [
{
name: 'Philip',
age: 18,
},
{
name: 'Tom',
age: 20,
},
],
};

但是有一种特殊情况,就是类型定义有时是无法修改的,比如定义在第三方库中,这时候我们不直接赋值,而是把返回值push到数组中,这样就不会报错了。

1
2
3
4
5
6
7
8
9
10
const data: response = {
students: [
{
name: 'Philip',
age: 18,
},
],
};

data.students.push({ name: 'John', age: 20 })