Skip to content
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

[docs] Understanding better why I don't need zod and/or more info on RT validation #39

Closed
lkj4 opened this issue Oct 3, 2022 · 7 comments

Comments

@lkj4
Copy link

lkj4 commented Oct 3, 2022

I saw on HN the discussion on zod. I'm not fully into zod but there's one thing which gets you less code in zod:

Usually, I'd declare TS types for some entities, e.g. a type user = { _id: ObjectId; email: string }. Then, I'd still need the declaration for the runtime validation. I could use class-validators and use decorators on a class-based type def, I could use zod, yup or whatever. I any case I'd need another block of code and my code wouldn't be DRY anymore, even with decorators which double definitions.

With zod alone, I'd create the zod RT validation declaration only and if need the user's type I just do z.infer, so I have only one single and DRY code block for type def and runtime validation.

Maybe Telefunc solves this problem too, not sure about it, hence you need to give more details on your RT validation and more examples.

Otherwise, congrats to such a nice API you created, haven't seen anything else which is as beautiful designed! 🙂

@brillout
Copy link
Owner

brillout commented Oct 3, 2022

In theory that's a good point but I don't foresee this to happen in practice. Let me elaborate.

If you define a generic endpoint updateTodoItem(), then yes, being able to re-use your zod types is nice:

// TodoItem.telefunc.ts

export { updateTodoItem }

import { z } from "zod"

const TodoItem = z.object({
  text: z.string(),
  completed: z.boolean()
})
type TodoItem = z.infer<typeof TodoItem>

async function updateTodoItem(id: string, props: Partial<TodoItem>) {
  const todoItem = await db.TodoItem.findOne({ id })
  await todoItem.update(props)
}

But this is considered bad practice in Telefunc's world.

Instead, the idiomatic way of using Telefunc is to define tailored telefunctions:

// TodoList.telefunc.ts

export { onTextUpdate }
export { onCompleteToggle }

// Note that we don't even have to use `shield()` here because Telefunc is able to infer it
async function onTextUpdate(id: string, text: string) {
  const todoItem = await db.TodoItem.findOne({ id })
  await todoItem.update({ text })
}

// The point being that we don't need our Zod type to define the types of our telefunction arguments
async function onCompleteToggle(id: string) {
  const todoItem = await db.TodoItem.findOne({ id })
  await todoItem.update({ completed: !todoItem.completed })
}

With such tailored telefunctions, I don't see much use case for using zod types.

Don't take me wrong, I really am open to support Zod (and other runtime type checking libraries), I just want to see concrete use cases for it.

As for documentation, you're right, the Telefunc docs currently do a poor job on showcasing that Telefunc just works without unnecessary frills.

@lkj4
Copy link
Author

lkj4 commented Oct 3, 2022

Ok, thanks for elaborating! So, Telefunc just does the validation automagically? I just type the function arguments and Telefunc does also the RT validation? And this also works with nested object parameters?

@brillout
Copy link
Owner

brillout commented Oct 3, 2022

In case you're curious, this is how Telefunc does it: https://github.com/brillout/telefunc/blob/4bf6454f0270c5779d078046d70e956c57cdfb33/telefunc/node/server/shield/codegen/transformer.ts.

I just type the function arguments and Telefunc does also the RT validation?

Yes, although it only works if the function argument types only use types defined in the .telefun.js file (the RT infering doesn't work when types are imported). I think that limiation is ok, since tailored telefunctions usually have simple types.

And this also works with nested object parameters?

Yes.

I believe that this automatic RT validation works for most telefunctions. For more advanced use cases, the user can do it manually.

@lkj4
Copy link
Author

lkj4 commented Oct 3, 2022

(the RT infering doesn't work when types are imported).

What about classes (which I often use as type defs)? Can I import them?

@brillout
Copy link
Owner

The RT inferring only works with types you define within the .telefunc.ts file.

But, really, the idea is that since telefunctions are tailored they have only few and simple arguments. So AFAICT the current RT inferring system will work for the the (vast?) majority of telefunctions.

That said, I'm eager to discuss and an re-consider things as you stumble upon limitations while implementing an app.

FYI I just released a new version, including dev performance improvements.

Sorry for the late replay - but now that I'll be focusing 80% of my time on Telefunc in the next coming weeks and months.

Let me know if you have any other question.

I'm leaving this ticket open until the docs properly explain Telefunc's approach.

@brillout
Copy link
Owner

Alright, so we managed to make the runtime type checker work in all scenarios. If things work as expected, you won't need shield() nor zod anymore. Telefunc will just runtime check your telefunctions for you, and it will just work.

Once the PR is merged #40 we'll be able to test the new implementation on real world apps. Let's see.

What about classes (which I often use as type defs)? Can I import them?

Yes, with the new implementation you'll be able to do this. There are actually examples/ that do this.

@brillout
Copy link
Owner

brillout commented Nov 9, 2022

Done. Use the latest Telefunc version to get complete automatic runtime validation. No need for Zod anymore. (You can still use it though if you want.)

@brillout brillout closed this as completed Nov 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants