I've started learning typescript from the official documentation, and came across the topic of intersecting types. So, in order to get a proper understanding of how type intersection works, i decided to write up a custom type. The FoodItems interface requires to be an array of objects and same for side. However, whenever I try intersect the two types, every representation of FoodOrder fails. I don't understand why that happens and what i'm doing wrong.
interface FoodItems {
[index: number]: {name: string, quantityPerOrder: number};
}
interface FoodSide {
[index: number]: {sideName: string, sideQuantity: number};
}
let foodItem: FoodItems = [{name: "Fried Chiken", quantityPerOrder: 2}, {name: "Burger", quantityPerOrder: 1}];
let foodSide: FoodSide = [{sideName: "gravy", sideQuantity: 1}];
type FoodOrder = FoodItems & FoodSide;
let food: FoodOrder;
The declaration
let food: FoodOrder = [[{name: "Fried Chiken", quantityPerOrder: 2}],[{sideName: "gravy", sideQuantity: 1}]];
gives me the following error:
index.ts:14:24 - error TS2322: Type '[{ name: string; quantityPerOrder: number; }]' is not assignable to type '{ name: string; quantityPerOrder: number; } & { sideName: string; sideQuantity: number; }'.
Type '[{ name: string; quantityPerOrder: number; }]' is not assignable to type '{ name: string; quantityPerOrder: number; }'.
14 let food: FoodOrder = [[{name: "Fried Chiken", quantityPerOrder: 2}],[{sideName: "gravy", sideQuantity: 1}]];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index.ts:14:70 - error TS2322: Type '[{ sideName: string; sideQuantity: number; }]' is not assignable to type '{ name: string; quantityPerOrder: number; } & { sideName: string; sideQuantity: number; }'.
Type '[{ sideName: string; sideQuantity: number; }]' is not assignable to type '{ name: string; quantityPerOrder: number; }'.
14 let food: FoodOrder = [[{name: "Fried Chiken", quantityPerOrder: 2}],[{sideName: "gravy", sideQuantity: 1}]];
An intersection type requires food
to be both a valid FoodItems
object and a valid FoodSide
object.
Remember: an intersection type I = A & B
means that the set of values of type I
is the intersection of the sets of the values of types A
and B
. Since every value of type I
is at the same time a valid A
and a valid B
, it follows that the properties of the intersection type I
must be the union of the properties of the types A
and B
.
Likewise, a union type U = A | B
means that the set of values of type U
is the union of the sets of the values of types A
and B
. Since every value of type U
is either a valid A
or a valid B
, it follows that the properties of the union type U
must be the intersection of the properties of the types A
and B
.
So, what you are saying is that FoodOrder
is a type which can be indexed by a number and it returns a FoodItems
but at the same time it also returns a FoodSide
when it is indexed by a number.
A value of such a type cannot exist, so you actually can't construct anything that would be legal to assign to food
.
What would be possible is something like this:
interface FoodItem {
name: string
quantityPerOrder: number
}
interface FoodSide {
sideName: string
sideQuantity: number
}
interface FoodOrder {
[index: number]: FoodItem & FoodSide
}
let food: FoodOrder;
food = [
{
name: "Fried Chiken",
quantityPerOrder: 2,
sideName: "gravy",
sideQuantity: 1
}
];