Use TypeScript types for check in methods

One other thing that I forgot to mention about zod with zodern:relay is that the React-Hook-Form library also has a fantastic zod integration so you can share you schema’s across client and server, get validated and type safe method params, form data, as well as a type aware form integration. If you are passionate about type safety you’ll absolutely love this, and if you’re not yet, you will be after using tools like this for a while.

There is one thing that’s still missing from Meteor’s type safety story though. Currently if you pass a type to your meteor collection it will set up inference for all of the methods on the collection and when you run a find or find one, it will return a document or a cursor of documents with that type you specified. But what if you have a Profile type and it has a firstName, lastName, bio etc. you pass this to the collection via the type parameter and that’s the type of documents. Then you do something quite normal and you specify that you only want the firstName field in the find method options. Now the type for the return lies and tells our tooling that all the fields are available on each document of the result set. For some this might not seem like that big of a deal, but If you’ve ever worked with a data stack like TRPC with Prisma you understand the DX that you are missing out on. This E2E type safety all the way from the database to the client, this for me, is the Holy Grail, and I’m hoping to make this a reality over the next few months by helping to surface a bunch of code written by Evan Broder for his Jolly Rodger project.

Do you mean this in the context of subfields? So fields like:

Meteor.user().profile.firstName
Meteor.user().profile.lastName

//or

Meteor.user().profile: {
  firstName: 'John',
  lastName: 'Doe',
}

?

We actually don’t use that as DDP has no reactivity on subfields

For example explaines this. Or has this been solved between in case we missed it?

As for this issue we just name fields properly as top-level fields which works out:

Meteor.user().firstName
Meteor.user().lastName

No, I’m just talking TypeScript in this case. I’ve always been a staunch advocate of keeping a flat document structure due to this limitation of Meteor’s mergebox, which is why I created socialize:user-profile for the example scenario, but that’s a topic for another time.

To clarify what I mean above take the following code as an example.

import { Mongo } from 'meteor/mongo';
import z from 'zod';

export const ProfileSchema = z.object({
  firstName: z.string(),
  lastName: z.string(),
  birthDate: z.date(),
  bio: z.string(),
});

export type Profile = z.infer<typeof ProfileSchema>;
export const ProfilesCollection = new Mongo.Collection<Profile>('profiles');
export const p1 = ProfilesCollection.findOne({ firstName: 'John' });
export const p2 = ProfilesCollection.findOne({ firstName: 'John' }, { fields: { firstName: 1 } });

No we see here that we have 2 similar queries to find a single document, the difference is that we restrict the second one to the firstName field using { fields: { firstName: 1 }}. This of course means that the return will be an object with the shape { _id: string, firstName: string } or it will be undefined if no document is found. The issue is that if we examine the information typescript knows about this return, we find out that it thinks we have a full profile when a document is found as exampled by this screenshot using 2 slash to surface TypeScript info.

If you notice, it also doesn’t know that there is going to be an _id field on the document as well.This means TypeScript has given us improper information which is a source of totally preventable runtime errors.

If Meteor is ever to be taken as a serious tool for creating large scale codebases, the type safety story is going to have to get a lot better.

Can someone please give me (a related) advice?

It looks like I am unable to use zodern:relay in a Svelte project (and React probably as well).

Does it still work?

Is GitHub - Grubba27/meteor-rpc: Meteor Methods Evolved something I should prefer (it doesn’t look as simple as relay)?

Has anyone made any of these work with Svelte?

I have this working fine in React. This error looks like the Babel plugin isn’t working properly.

Thanks, I looks like it doesn’t work on Windows :(.

This is now fixed. The latest version of the babel plugin is able to run on Windows.

Amazing, thank you zodern. There is one more issue I logged as a bug (with a workaround). I can confirm the type checking is working well on Windows now.