Imagine I am creating a directory of tenants in a shopping center, which can be either shops or restaurants. These tenants fall into various categories:
type ShopTypes =
| `Accessories`
| `Books`
| `Clothing`;
type RestaurantTypes =
| `Dive Bar`
| `Elevated`
| `Family`;
type Tenant<TenantCategory extends `shop` | `restaurant` = `shop`> = {
category: TenantCategory;
categoryType: TenantCategory extends `shop` ? ShopTypes : RestaurantTypes;
label: string;
};
To simplify the process, I plan to organize the tenants as an array of arrays and utilize a function to convert each "row" into a Tenant
:
function toTenantList(...items: Array<
[`shop` | `restaurant`, ShopTypes | RestaurantTypes, string]
>): Array<Tenant> {
return items.map(([category, categoryType, label]) => ({
category,
categoryType,
label,
}));
}
const tenants: Array<Tenant> = toTenantList(
[`shop`, `Accessories`, `Alice's Accessories`],
[`restaurant`, `Dive Bar`, `Dan's Dive`],
[`shop`, `Books`, `Barry's Books`],
[`restaurant`, `Elevated`, `Exquisite Epicure`],
);
An error is generated:
Type '{ category: "shop" | "restaurant"; categoryType: ShopTypes | RestaurantTypes; label: string; }[]' is not assignable to type 'Tenant<"shop">[]'.
Type '{ category: "shop" | "restaurant"; categoryType: ShopTypes | RestaurantTypes; label: string; }' is not assignable to type 'Tenant<"shop">'.
Types of property 'category' are incompatible.
Type '"shop" | "restaurant"' is not assignable to type '"shop"'.
Type '"restaurant"' is not assignable to type '"shop"'.
In essence, TypeScript is concerned that a RestaurantType
might be placed in a shop
row, and vice versa.
How can I specify the requirement that if a row represents a shop
, it must have a ShopType
, and if it represents a restaurant
, it must have a RestaurantType
?