'Infer narrow type from parent object referencing itself in typescript
I would like to constrain a parameter type of a callback function that is inside an object like this:
makeObj({
items: [
{
value: "foo",
func(items) {}
},
{
value: "bar",
func(items) {}
}
]
});
I want to constrain the parameter items of func to "foo" | "bar". The values of value can be any string though.
I already have this, but it obviously doesn't work:
interface MyObject<T extends string, Values extends readonly MyObject<T, Values>[]> {
value: T;
func: (items: Values) => void;
}
interface Items<T extends string, Data extends readonly MyObject<T, Data>[]> {
items: readonly [...Data];
}
function makeObj<T extends string, Data extends readonly MyObject<T, Data>[]>(opt: Items<T, Data>) {
return opt;
}
makeObj({
items: [
{
value: "foo",
func(items) {}
/* Error on "func":
Type '(items: MyObject<string, unknown>) => void' is not assignable to type '(items: unknown) => void'.
Types of parameters 'items' and 'items' are incompatible.
Type 'unknown' is not assignable to type 'MyObject<string, unknown>'.
*/
},
{
value: "bar",
func(items) {} // same error on "func"
}
]
});
Some background info:
I'm writing a program that has some "actions" defined. Each action is a function in an object to describe the function (give it a name, description, input type, output type, secondary input type). The secondary input relies on user provided data. Each item of this data has a name and defined type. Its value is provided by the end user. Depending on the value of other items an item can be displayed to the user or not. This last part is controlled by the callback function in question.
I have all this already set up with narrow type inference to not make any mistakes while writing each action but this narrow type inference breaks down regardless of which type the callback function has. Either because it can't infer the narrow type anymore, or because I get a type error (e.g. when I use object as type for the parameter (I ultimately want to use an object as the parameter, not just a string)).
This narrow type inference works like this: typescript - Infer/narrow function argument from sibling property
Edit:
I would like a solution where I don't have the type embedded in the function parameter but as an interface/type that I can reference like:
interface Magic<MagicParam> {
items: MagicParam;
}
makeObj<MagicParam>(opt: Magic<MagicParam>) {
return opt;
}
Magic can be an interface or type and can have any number of type parameters. makeObj too can have any number of type parameters.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
