Reputation: 4968
I'm trying to write a function that will return an object whose keys are going to be the same as the values of the input array:
type PathParam = 'userId' | 'groupId' | 'commentId';
function usePathParams(params: PathParam[]) {
return params.reduce(
(acc, param) => ({ ...acc, [param]: 'whatever' }),
{} as Record<typeof params[number], string>,
);
}
// OK
const { userId } = usePathParams(['userId', 'commentId']);
// Should be an error but is not
const { userId, groupId } = usePathParams(['userId', 'commentId']);
// Passing a tuple doesn't seem to work either
const { userId, groupId } = usePathParams(['userId', 'commentId'] as const);
Is there any way to achieve this?
Upvotes: 0
Views: 296
Reputation: 42298
In order to get an error on your second case, we need to use a generic to know which specific keys were passed.
function usePathParams<Params extends PathParam>(params: Params[]) {
return params.reduce(
(acc, param) => ({ ...acc, [param]: 'whatever' }),
{} as Record<Params, string>,
);
}
We now get the desired error Property groupId
does not exist on type Record<"userId" | "commentId", string>
Your third example still has an error because as const
makes the tuple readonly
. If you wanted to support this, you would change the function arguments to (params: readonly Params[])
. That actually allows both readonly and mutable arrays. It says that we only require read functionality.
Upvotes: 1