0%

typescript-array-literal-type

TypeScript Array Literal Type

问题提出

考虑下面的类型定义:

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

注意这里的students是一个数组字面量,而不是普通的数组,数组中的元素是一个对象,对象中有nameage两个属性。我们在使用这个类型的时候,可能会遇到这样的情况:

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

这样的情况下,data是一个符合response类型的对象,但是students数组中的元素个数是不对的,因为students的类型定义是一个元素的数组字面量。所以我们不能传入两个元素(这相当于把students当作数组类型来使用,而不是当作数组字面量来使用)。所以TS会给出如下提示:

1
2
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是一个数组,数组中的元素是一个对象,对象中有nameage两个属性。这样的定义,students数组中的元素个数是不确定的,可以是0个或者多个。

也可以使用[]来定义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 })