-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: declare document TypeScript types in createClient()
#238
Conversation
Codecov Report
@@ Coverage Diff @@
## master #238 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 23 23
Lines 363 363
Branches 67 67
=========================================
Hits 363 363
Continue to review full report at Codecov.
|
size-limit report 📦
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job, looks good to me!
Maybe it's worth adding an example for the CreateClient
extends? Up to you!
src/client.ts
Outdated
export interface CreateClient { | ||
< | ||
DocumentTypeMap extends Record<string, prismicT.PrismicDocument> = Record< | ||
string, | ||
prismicT.PrismicDocument | ||
>, | ||
>( | ||
...args: ConstructorParameters<typeof Client> | ||
): Client<DocumentTypeMap>; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any value to allow extension of the whole createClient()
function type?
As-in, can we make it so that you only need to extend the document type map?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed to pair a repository name literal to its document types. This allows this new system to support apps with multiple repositories, each with their own set of document types.
For example:
declare module "@prismicio/client" {
interface CreateClient {
(
repositoryNameOrEndpoint: "foo",
options?: prismic.ClientConfig | undefined
): prismic.Client<FooDocumentTypes>;
(
repositoryNameOrEndpoint: "bar",
options?: prismic.ClientConfig | undefined
): prismic.Client<BarDocumentTypes>;
}
}
While this is a rare situation, it ensure we are not locked into only supporting a single global config.
Since this code would typically be generated rather than hand-written, the extra boilerplate is okay, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I was thinking it'll be something like that, great!
From @chamois-d-or (Alexandre): Any consideration about graph queries? |
Thanks for the review! 🙂 (And the nice refactor to use
Augmenting I'll update the "With TypeScript" example to use this new API. Manual usage (i.e. without touching Maybe we should add another example for JSDoc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect 👌
Oops, I missed this question:
Automatically typing GraphQuery or FetchLinks is out of scope for this PR. This PR still allows developers to manually extend the return type like this: import * as prismic from "./index";
import * as prismicT from "@prismicio/types";
type PageDocument = prismicT.PrismicDocument<
{
foo: prismicT.KeyTextField;
parent: prismicT.LinkField;
},
"page"
>;
type AllDocumentTypes = PageDocument;
const client = prismic.createClient<AllDocumentTypes>("qwerty");
const graphQuery = `
{
page {
parent {
...on page {
title
}
}
}
}
`.trim();
// Manually extend PageDocument to include the GraphQuery fields.
const home = (await client.getByUID("page", "home", {
graphQuery,
})) as PageDocument & {
data: {
parent: {
data: {
title: prismicT.TitleField;
};
};
};
}; The In the future, we could support an automatic GraphQuery/FetchLinks => TypeScript conversion that would simplify the above approach, but this is not planned currently: const home = (await client.getByUID("page", "home", {
graphQuery,
})) as PageDocument & PageParentGraphQuery; |
createClient()
createClient()
Types of changes
Description
This PR adds the ability to declare document types queryable by the client.
Client methods that accept an explicit document type, such as
getByType()
andgetSingle()
, can automatically return the appropriate document type. Furthermore, these methods are typed to only accept document type IDs that have been provided to the client.Methods that do not explicitly accept a document type return a union of all possible document types. Documents can be type narrowed at runtime by checking their
type
property.Maintaining backwards compatibility
Query methods still accept a
DocumentType
type parameter to explicitly declare the returned document type. This is useful if types were not provided tocreateClient()
or the document type passed to a query method is not a constant (i.e. typed asstring
).Backwards compatibility is maintained compared to the previous TypeScript API.
If types are provided to
createClient()
, explitly provided document types to a query method must be assignable to the client-level types.Client type augmentation
This PR also adds the ability for
createClient()
type augmentation through a newCreateClient
interface. This lets third-party packages, such as those generating types, to automatically link a literal repository name to a set of document types.With this module augmentation in place,
createClient("qwerty")
will automatically useAllDocumentTypes
.Checklist:
🦑