When working with Typescript ^3.8, we have an interface defined as follows:
interface IEndpoint { method: 'get'|'put'|'post'|'patch'|'delete', path: string }
Additionally, there is a constant declared like this:
const endpoint = { method: 'get', path: '/first/:firstId/second/:secondId' }
In this scenario, :firstId
and :secondId
are dynamic path parameters that will be provided at runtime. A function exists that takes the endpoint and a parameter values object to build the final URL.
function buildEndpointUrl(endpoint: IEndpoint, map: {[key: string]: string}): string;
For example:
// This will yield url '/first/123/second/456'
const url = buildEndpointUrl(endpoint, {firstId: '123', secondId: '456'});
The issue arises when invalid data is passed as the second parameter. How can we define IEndpoint
and buildEndpointUrl
to ensure that the compiler throws an error if a required key is missing in the object?
A potential solution attempted was:
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
);
However, the last line triggers a compiler error:
TS1023: An index signature parameter must be either "string" or "number"
The expectation was for T[number]
to be treated as equivalent to string
due to
T extends ReadonlyArray<string>
, but it seems not to be the case. What adjustments should be made in the definition to enhance type safety?