-
Notifications
You must be signed in to change notification settings - Fork 152
Refactoring of the types for collection configurations #530
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
Conversation
🦋 Changeset detectedLatest commit: 2ade434 The changes in this PR will be included in the next version bump. This PR includes changesets to release 12 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
More templates
@tanstack/angular-db
@tanstack/db
@tanstack/db-ivm
@tanstack/electric-db-collection
@tanstack/query-db-collection
@tanstack/react-db
@tanstack/rxdb-db-collection
@tanstack/solid-db
@tanstack/svelte-db
@tanstack/trailbase-db-collection
@tanstack/vue-db
commit: |
|
Size Change: +108 B (+0.16%) Total Size: 66.7 kB
ℹ️ View Unchanged
|
|
Size Change: 0 B Total Size: 1.18 kB ℹ️ View Unchanged
|
|
@ignatz I had a look at the trailbase collection to see if it needs similar changes. But i wasn't sure. The changes in this PR are needed for collections that accept a user-provided schema. At the type level the trailbase collection does accept the However, looking further at the
|
|
@kevin-dp , thanks for improving inference. The TB collection was very closely modeled after the electric one. It has been a few days. Let me have a quick look, to make sure I'm up-to-date with the latest changes, and come back to you 🙏 |
IIUC, for this to work the trailbase client would need to emit a zod schema for tanstack/db to use, similar to how drizzle produces one that is used in the example. I think that's a fine approach but I wouldn't want to hold you up.
This seems like the straightforward approach. Removing the schema argument from the example seems to just work. Do you foresee any issues with this approach? Naively, I'd be leaning (1). Thanks 🙏 |
Yep that's what i was thinking. Since the user can provide a custom parser it seems that they can do in the parser what the schema would usually do. Although it may be nicer with a schema. Wondering now if from a user perspective it makes sense to provide a parser to parse |
Not really, the schema is usually provided by the user. It's optional though. If the user provides a schema, then tanstack/db uses that schema to validate the input and possible transform it into the output type. Tanstack/db can also infer the type of the items in the collection from the schema. If no schema is provided, then ts/db doesn't do any validation and infers the type of the collection from the |
The TrailBase client is also typed. If schema, it would make sense to infer it. Otherwise, there's the risk of skew and parlor usability. The |
|
@ignatz if it makes sense to replace |
…alOnlyCollectionOptions
…d of the input type
…ionConfig no longer has this type param
8ccf7db to
bdeaa91
Compare
samwillis
left a comment
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.
LGTM ![]()
This PR addresses #396 and supersedes #401. It refactors the types for collection configs.
Problem:
ResolveTypehelper doesn't work with inferred typesThe main problem was that we had different type parameters
TExplicit,TSchema, andTFallbackand we would resolve the type from them based on theResolveTypehelper. WhileResolveTypeworks correctly when you provide it the types, it doesn't play nicely when it comes to type inference. Essentially, the compiler sometimes had to infer the types forTExplicit,TSchema, andTFallbackbased onResolveType<TExplicit, TSchema, TFallback>and that doesn't work:This is one of the problems, there were many other type problems related to this logic. For instance, a user could provide an explicit type to a collection config and then pass in a
getKeyfunction whose type doesn't correspond to the explicitly passed type, and it would type check without errors while you would expect it to complain because the argument of thegetKeyfunction has a different type thanTExplicit.Solution
Remove
ResolveTypeand infer the types from the schemaWhen creating a collection configuration the user can either pass in a schema or not pass in a schema. If a schema is provided the types need to be inferred from the schema. If no schema is provided, they need to be inferred from
getKey. Note: if a schema is provided then the schema types and thegetKeytypes must match.To track whether or not a schema is provided we need to overload the factories that create collection options. This is the new implementation of
createCollection:Notice that in the first overload, Typescript can infer
Tfrom the schema that the user provides. We then derive the input and output types from that schema, i.e. fromT. In the 2nd overload, we explicitly require the schema to be absent (i.e.schema?: never) and thus the input and output types are the same as they are justT. Note thatTcorresponds to the type of values that are handled by thegetKeyfunction from the config. So Typescript can infer it from that function, or the user can pass it explicitly (in which case it must typecheck with the actual types of thegetKeyfunction).So far so good, we managed to remove the
ResolveTypelogic.Track schemas in the output type of the create collection config factories
We managed to remove the
ResolveTypelogic but thecreateCollectionfunction now needs to know whether a schema was provided or not. However, our existing collection config factories don't provide that information. Consider for instance the localOnlyCollectionOptions factory implementation:The return type of this factory function is:
Since
CollectionConfigdefined a propertyschema?: TSchemathat means that we can't actually know whether or not the schema was provided (since it's always typed as an optional). But we need to know whether it is provided or not in order to pick the right overload.Hence, we need to also overload the config factories such that their return type is explicit about whether or not the schema was provided:
Finally, now we are tracking whether or not the schema was provided throughout the factories and all types can be inferred correctly.