'Constrain tuple values where 2nd value is constrained by the 1st value
I can do the following easily with a function, but to create a simpler API for the consumer I want to do it with a tuple.
Say I have 2 simple React components that take different props:
const Text = ({ value }: { value: string }) => <span>{value}</span>;
const PrefixedText = ({ prefix, value }: { prefix: string; value?: string }) => (
<span>{value ? `${prefix}${value}` : ''}</span>
);
And an object that references them:
const renderPropMap = {
text: Text,
prefixedText: PrefixedText
};
type RenderPropMap = typeof renderPropMap;
Now I want to create a type that is a tuple where the 1st element is a key of renderPropMap ('text' or 'prefixedText') and the 2nd element is the props of the component at the key of the given 1st element. AND I would like the IDE to auto-suggest the 2nd element once the first has been entered.
I can easily create a function that does this with its arguments and returns the desired tuple:
type RenderProps<R extends keyof RenderPropMap> = [R, Parameters<RenderPropMap[R]>[0]];
function setRender<R extends keyof RenderPropMap>(...args: RenderProps<R>) {
return args;
}
Now when I pass 'text' as the first parameter it auto-suggests { value: string } for the second parameter, and similarly if I pass 'prefixedText' is suggests { value?: string, prefix: string }. Also Typescript infers R from the first parameter so the consumer doesn't need to pass in the type parameter. Nice.
But as I said, I don't want to use a function, I just want the consumer to provide a tuple. I was able to come up with this:
type ComponentRef = 'text' | 'prefixedText';
type RenderPropsTuple = ComponentRef extends infer R
? R extends ComponentRef
? RenderPropMapValue<R> extends (...args: any) => JSX.Element
? [R, Parameters<RenderPropMapValue<R>>[0]]
: never
: never
: never;
Now Typescript does complain if I define an invalid tuple BUT I don't get auto-suggestion for the 2nd element. In fact I get auto-suggestion of all the possible props for both components no matter which key I put as the first element.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
