In my client server application, I use REST calls for communication.
To avoid using the wrong types by mistake, I have defined all RestCalls in a common file (excerpt):
type def<TConnection extends Connections> =
// Authentication
TConnection extends '/auth/password/check/:login->get' ? Set<void, { found: boolean }, void, false>
: TConnection extends '/auth/password/register->post' ? Set<RegisterAccount<Login>, void, void, false>
: TConnection extends '/auth/password/login->post' ? Set<Login, void, void, false>
...
The url and method are encoded in the string, including express url parameters (/ :).
Set
determines the data in the body and if authentication checks should be performed.
- request
- response
- response on error
- if authentication is needed
type Set<Input extends (Object | void), result extends (Object | void), Error extends string | object | void, NeedsAuthentication extends boolean = true> = {
input: Input, result: result,
error: DefaultError<Error>,
authenticated: NeedsAuthentication
};
I can then utilize the following types to access the correct values:
...I would now like to dynamically determine at runtime whether authentication is required for a specific call. Is there a way to achieve this without workarounds?
I want to implement the following function:
function needsAuthentication<T extends Connections>(test: T): NeedsAuthentication<T> {
// todo find out if authentication is actually required for this url
}
This function is not part of the transmitted data but is encoded in the type mapping. The compiler will accurately map it to true or false for const strings at compile time.