I am currently working on developing a TypeScript interface that can automatically infer the function signature inside an object based on the adjacent key's presence and type, aiming to create a more ergonomic and generic interface.
Here is what I have implemented so far, which is partially functional for my specific use case:
interface BaseColumnDefinition<T extends Record<string, any>> {
label?: string;
key?: keyof T | undefined;
}
interface KeylessColumnDefinition<T extends Record<string, any>> extends BaseColumnDefinition<T> {
key?: undefined;
render: (value: T) => JSX.Element;
}
interface KeyedColumnDefinition<T extends Record<string, any>> extends BaseColumnDefinition<T> {
key: keyof T;
render: (value: T[this["key"]]) => JSX.Element;
}
type ColumnDefinition<T extends Record<string, any>> =
| KeyedColumnDefinition<T>
| KeylessColumnDefinition<T>;
const definitionWithoutKey: ColumnDefinition<{ name: string; id: string; value: number }> = {
label: "Name",
render: (value) => <></>, //correctly infers the type of render is (value: {name: string, id: string, value: number}) => JSX.Element
};
const definitionWithKey: ColumnDefinition<{ name: string; id: string; value: number }> = {
label: "Name",
key: "value",
render: (value) => <></>, //should infer a type of (value: number) => JSX.Element, instead infers the union of types from the T parameter i.e. (value: string | number) => JSX.Element
};
If there are any suggestions or solutions to improve this implementation and ensure correct signature inference based on the "key" value in the object, that would be greatly appreciated.