'Typescript dynamic type inference
I want the interface Key to be able to infer the type of items in the onChange method from the format value. Whether this idea works in typescript.
interface Key<T extends Record<string, any>> {
format?: keyof T;
items: T[];
/** The items parameter waits to be inferred */
onChange(items): void;
}
interface Datum {
value: {
inner: string;
};
}
type NoFormatKeyExpect = Datum;
const noFormatKey: Key<Datum> = {
items: [{ value: { inner: "Hello" } }],
onChange(items) {
/** If the object has no format property, I want items to be inferred as an array of NoFormatKeyExpect. */
},
};
interface HasFormatKeyExpect {
inner: Datum["value"]["inner"];
}
const hasFormatKey: Key<Datum> = {
format: "value",
items: [{ value: { inner: "Hello" } }],
onChange(items) {
/** If the object has format property, I want items to be inferred as an array of HasFormatKeyExpect. */
},
};
I want code hint when I write hasFormatKey onChange method. How do I write the interface Key?
Let me simplify the example a little bit.
type ItemInfer<T, F> = F extends keyof T ? Pick<T, F> : T
interface ListProps<T extends Record<string, any> = Record<string, any>, F extends keyof T = keyof T> {
format?: F
onChange?(items: ItemInfer<T, F>): void
}
// If i dont't write the second generic, the item of the onChange method has no code hints.
// Is there a way to get code hints without writing a second generic?
const demo1: ListProps<{ a: string; b: number }> = {
format: 'b',
onChange(item) {
// Why can't item be inferred to be {b:number}.
item.b // There is no code hint for item here
},
}
Solution 1:[1]
A quick way would be for you to implement a switch case and check the item type, something like:
onChange(items) {
/** If the object has no format property, I want items to be inferred as an array of NoFormatKeyExpect. */
switch(items){
case Array:
console.log("It`s an array");
break;
case Number:
console.log("It`s a number");
break;
case String:
console.log("It`s a string");
break;
default:
break;
}
},
And you could also apply the Strategy design pattern (I think), which would be to create a generic and abstract implementation for items ItemsInterface, and item extensions, like ItemOne, and in your onChange function each item calls an abstract method to be implemented in the item extensions.
onChange(items: ItemInterface) {
/** If the object has no format property, I want items to be inferred as an array of NoFormatKeyExpect. */
items.onChange()
},
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Maykon Meneghel |
