In TypeScript version 5.0.2
I am working on a function that returns an array of 3 functions. I want the purchase
function to be typed in such a way that it only requires a requirement
parameter if the specified product has one (as indicated in the products
type object). Currently, both the purchaseSoda()
and purchaseBeer()
functions require a requirements
parameter. However, there are no requirements for soda, so I expect only the purchaseBeer()
function to throw an error since no requirements object is passed to it.
I do not want to have to call a method that does not require a parameter like this: purchaseSoda(undefined);
type InventoryItem<Product, Restrictions = undefined> = {
product: Product,
restrictions: Restrictions
}
type Beverage = { sizeInOunces: number, price: number };
type Book = { title: string, price: number }
type AgeRequirement = { age: number }
type products = {
"soda": InventoryItem<Beverage>,
"beer": InventoryItem<Beverage, AgeRequirement>,
"comic": InventoryItem<Book>,
"Adult Magazine": InventoryItem<Book, AgeRequirement>
};
const getItem = <
productName extends keyof products,
item extends products[productName],
product extends item["product"],
restrictions extends item["restrictions"]
>
(name: productName): [
(item: product) => void,
(restrictions: restrictions) => product,
() => void
] => {
const addItemToInventory = (item: product) => { throw new Error("omitted for stackoverflow"); }
const cancelPurchase = () => { throw new Error("omitted for stackoverflow"); }
const purchase = (restrictions: restrictions): product => { throw new Error("omitted for stackoverflow"); }
return [addItemToInventory, purchase, cancelPurchase];
}
const [addSoda, purchaseSoda, cancelPurchaseSoda] = getItem("soda");
const [addBeer, purchaseBeer, cancelPurchaseBeer] = getItem("beer");
purchaseSoda(); // Shouldn't Require a Param
purchaseBeer(); // Should Error here, because the beer product has an age requirement.
purchaseBeer({ age: 21 }); // Should require a param
I have attempted using never
and null
as default assignments for the InventoryItem
.
I have converted the getItem
and purchase
methods into functions with overrides.
I have modified the return signature of getItem
:
(name: productName): [
(item: product) => void,
(() => product) |
((restrictions: restrictions) => product),
() => void
] => {
I have changed the signatures of the purchase
method to make the parameter optional (using '?'):
(name: productName): [
(item: product) => void,
(restrictions?: restrictions) => product,
() => void
] => {
const addItemToInventory = (item: product) => { throw new Error("omitted for stackoverflow"); }
const cancelPurchase = () => { throw new Error("omitted for stackoverflow"); }
const purchase = (restrictions?: restrictions): product => { throw new Error("omitted for stackoverflow"); }
Although this allows me to call purchaseSoda()
without a parameter, it also allows me to call purchaseBeer()
without one. However, purchaseBeer()
has an age requirement that needs to be included. Simply adding '?' did not solve my problem.
I have gone through several docs in attempts to solve this issue.
After spending a few hours experimenting with this, I feel stuck and would greatly appreciate any help or insights. Thank you for your time.