requestManager.request
and store.request
each take a generic that can be used to set
the return type of the content of the associated request.
const { content } = await store.request<User>({ ... });
// here content will be typed as a User
Caution
Note that this puts the burden on you to ensure the return type accurately portrays the result!
In all cases, the response will be a StructuredDocument<T>
where T
is the content type provided.
This approach allows for a lot of flexibility in designing great sugar overtop of the request infrastructure, but again, limits the amount of safety provided and should be used with great caution.
A better approach is to use builders and set the generic via inference.
The signature for request
will infer the generic for the content type from a special brand on the options passed to it.
import type { RequestSignature } from '@warp-drive/core-types/symbols';
import type { CollectionRecordArray } from '@ember-data/store/types';
import type User from '../models/user';
type MyRequest {
// ...
[RequestSignature]: CollectionRecordArray<User>
}
function buildMyRequest(...): MyRequest { /* ... */ }
const { content } = await store.request(
buildMyRequest(...)
);
// here content will be set to `CollectionRecordArray<User>`
Because builders are just functions that produce a request options object, and because this object can be branded with the type signature of the response, we can use this to create advanced more-strongly-typed systems.
For instance, imagine you had a query builder that validated and linted the query against a backing schema, such as you might get with GraphQL
const { content } = await store.request(
gql`query withoutVariable {
continents {
code
name
countries {
name
capital
}
}
}`
);