In Typescript ^3.8, given this interface...
interface IEndpoint { method: 'get'|'put'|'post'|'patch'|'delete', path: string }
and this constant...
const endpoint = { method: 'get', path: '/first/:firstId/second/:secondId' }
Note that :firstId and :secondId are path parameters that will be dynamically provided at runtime. I have a function that will take the endpoint and an object with param values, and return the url.
function buildEndpointUrl(endpoint: IEndpoint, map: {[key: string]: string}): string;
So, for instance:
// will set url to '/first/123/second/456'
const url = buildEndpointUrl(endpoint, {firstId: '123', secondId: '456'});
The challenge I'm facing is that the compiler will allow garbage to be passed as the 2nd param: how do I define IEndpoint and buildEndpointUrl so that the compiler throws an error if the object provided as the second parameter is missing a required key?
Here is what I've tried:
interface IEndpoint<T extends ReadonlyArray<string>> {
method: 'get'|'put'|'post'|'patch'|'delete',
path: string
}
const endpoint: IEndpoint<['firstId', 'secondId']> = {...};
function buildEndpointUrl<T extends ReadonlyArray<string>>(
endpoint: IEndpointConfig<T>,
map: {[key: T[number]]: string} // compiler error
);
the last line throws a compiler error:
TS1023: An index signature parameter must be either "string" or "number"
I expected T[number] to be equivalent to string since T extends ReadonlyArray<string> but apparently not. How should I setup my definition to add type safety?
[key: T[number]]: stringshould be[key: number]: stringIEndpoint<['firstId', 'secondId']>as the first function param, I want Typescript to infer that the second param must be of type{firstId: string, secondId: string}buildEndpointUrl(endpoint, ['firstId', 'secondId']);?