我无法理解我遇到的 typescript 错误背后的机制 - 我确信有一些基本的东西在我头顶上飞过时发出“嗖”的声音。
我只找到了 this关于该主题的问题,但虽然错误看起来相同,但设置对我来说似乎完全不同。
这是我引用的定义,为简洁起见。
type ApexAxisChartSeries = {
// ...
data:
| (number | null)[]
| {
x: any;
y: any;
// ...
}[]
| [number, number | null][]
| [number, (number | null)[]][];
}[]
这是一个错误的函数,它接受一个 {x:number, y:number}
数组。
function composeSeries(input: { x: number; y: number }[]) {
const series: ApexAxisChartSeries = [
{ name: "A", data: [] },
{ name: "B", data: [] },
];
input.forEach((datum) => {
series[0].data.push(datum); // <-- This line right here gives the error.
});
return series;
}
现在,让我感到困惑的是,根据类型定义,我希望 {x:number, y:number}
对象是 data
的完全有效元素>,但是 typescript 提示说
Argument of type
'{ x: number; y: number; }'
is not assignable to parameter of typenumber & { x: any; y: any; fillColor?: string | undefined; strokeColor?: string | undefined; meta?: any; goals?: any; } & [number, number | null] & [number, (number | null)[]]'
.Type
'{ x: number; y: number; }'
is not assignable to type'number'
.
我在这里想,如果类型定义使用联合,错误中的交集来自哪里?
作为附加上下文:
- 不仅仅是对象出错了。如果我使用
[x,y]
元组或只是一个数字数组,编译器仍然会活跃起来 - 我正在使用 TS 4.5.4
- 我非常肯定此代码中存在问题:TS playground 给出了相同的错误
作为引用,这是完整的类型定义:
type ApexAxisChartSeries = {
name?: string
type?: string
color?: string
data:
| (number | null)[]
| {
x: any;
y: any;
fillColor?: string;
strokeColor?: string;
meta?: any;
goals?: any;
}[]
| [number, number | null][]
| [number, (number | null)[]][];
}[]
非常感谢任何澄清!
编辑:可以在 TS Playground 上找到错误示例 here ,由@jcalz 提供
最佳答案
(T | U)[]
和 T[] | 是有区别的你[]
。第一种,每个数组元素可以是 T 或 U 类型。在第二个(与您的情况相对应)中,数组只能包含任一类型的元素。
您必须问自己的问题是:当 TypeScript 不知道变量是哪种类型的数组时,它如何知道允许哪些元素?
const myArray: string[] | number[] = [];
myArray.push(5); // Argument of type 'number' is not assignable to parameter of type 'never'.
以上面的例子为例。无论如何,TypeScript 都会抛出错误,因为无论您向该数组推送什么,都不会符合其中一种可能的类型。
好消息是 TypeScript 编译器很聪明,并且在您的情况下发现可以派生出符合所有可能条件的类型。该类型恰好是所有可能的元素类型的交集,是满足要求的最基本类型。
您的选择是要么使数组允许任何可能的类型,要么使该系列成为扩展任何一种类型的泛型。
选项A:数组元素可以是多种类型之一
type ApexAxisChartSeries = {
name: string,
data:
(number
| null
| { x: any; y: any; }
| [number, number | null]
| [number, (number | null)[]]
)[]
};
选项 B:泛型类型参数可以是多种类型之一
type ChartDataType = (number | null)
| { x: any; y: any; }
| [number, number | null]
| [number, (number | null)[]];
type ApexAxisChartSeries<T extends ChartDataType> = {
name: string,
data: T[]
}[];
function composeSeries<T extends ChartDataType>(input: T[]) {
const series: ApexAxisChartSeries<T> = [
{ name: "A", data: [] },
{ name: "B", data: [] },
];
input.forEach((datum) => {
const index = (true) ? 0 : 1;
series[index].data.push(datum);
});
return series;
}
composeSeries([{ x:1, y: 1}]); // returns { name, data: { x, y }[] }[]
关于typescript - 为什么这种类型的联合在 typescript 中被解析为一个交集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71313168/