fluent-json-schema icon indicating copy to clipboard operation
fluent-json-schema copied to clipboard

Compute TypeScript type

Open JSteunou opened this issue 4 years ago • 10 comments

🚀 Feature Proposal

I think it will be possible and convenient to add a way to expose the TypeScript type of each object schema

Motivation

I started, like the doc of fastify suggest, to use fluent-schema (which is awesome!) and json-schema-to-typescript to generate types... in separate files.

Also this method could be ok for those who prefer having separate files, separate schema & types, I am not a big fan of depending on a script to re-generate those types. And even with a banner saying do not modify this file, update the schema instead, this could be error prone.

Another way to handle the case would be to add the capacity to fluent-schema to generate types directly. It would allow users to export a schema and the matching interface or type from the same module, not depending on scripts, not having several files, not having a type written that can be modified, not having another library, ... You got the point, it would be just simpler :)

Example

To my opinion, a good example of API for this case is mobx-state-tree which allow to generate Interface or Type from a model

import {Instance} from 'mobx-state-tree'

const Todo = types
    .model({
        title: "hello",
        done: false,
    })

interface ITodo extends Instance<typeof Todo> {}
// => {title: string, done: boolean}

type TTodo = typeof Todo.Type
// => {title: string, done: boolean}

The helper Instance is from MobX State Tree here, not a TypeScript helper.

The bad news is, I don't know how to do this myself, but I can learn and help if needed :pray:

JSteunou avatar Aug 05 '20 08:08 JSteunou

I think this is hard to do, but maybe it got easier!

An alternative approach is https://github.com/sinclairzx81/typebox!

mcollina avatar Aug 05 '20 08:08 mcollina

I think it depends if you wanna be full JSON Schema compliant. $ref might be the most difficult point to solve because it can be async.

I will try typebox, sounds nice. I also discover https://github.com/keplr-team/typed-ajv which has the same approach than typebox. The trick is to define types of each function helper which define properties.

JSteunou avatar Aug 05 '20 09:08 JSteunou

It's an interesting feature, not sure how to tackle it. I have the feeling we need to bring an important part of the codebase in Typescript to deliver this. However, currently, I haven't bandwidth. But you are welcome to open a PR even with just as POC so we can maybe figure out the approach.

aboutlo avatar Aug 05 '20 13:08 aboutlo

Another example, for the record, that could help to build this feature, using TypeScript Conditional Types https://medium.com/@tiagosemoh/typescript-advanced-types-b17ad54a831e

This is the base of this library https://github.com/TCMiranda/joi-extract-type which seems very underestimated

I dunno if I would have the time to write a POC, having a bandwidth also very full :( So I share any resource I can find.

JSteunou avatar Aug 05 '20 14:08 JSteunou

Thank you so much for sharing typebox, I had the exact same issue in fluent-schema and typebox seems perfect.

Here's some example code for fastify if it helps anyone:

import { Type, Static } from '@sinclair/typebox';

const BodySchema = Type.Object({
	email: Type.String({ format: 'email' }),
	address: Type.String(),
});

server.route<{ Body: Static<typeof BodySchema> }>({
	method: 'GET',
	url: '/example',
	schema: {
		body: BodySchema
	},
	async handler(request, reply) {
		request.body.email;
	}
});

gc avatar Aug 06 '20 10:08 gc

We could learn something from TypeBox. It has an interesting approach. However fluent-schema starts from JSON Schema not Typescript.

On Thu, 6 Aug 2020 at 12:33, GC [email protected] wrote:

Thank you so much for sharing typebox, I had the exact same issue in fluent-schema and typebox seems perfect.

Here's some example code for fastify if it helps anyone:

import { Type, Static } from '@sinclair/typebox'; const BodySchema = Type.Object({ email: Type.String({ format: 'email' }), address: Type.String(),}); server.route<{ Body: Static<typeof BodySchema> }>({ method: 'GET', url: '/example', schema: { body: BodySchema }, async handler(request, reply) { request.body.email; }});

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/fastify/fluent-schema/issues/78#issuecomment-669849615, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJN2LAZ6E62F6ZZYS3TEI3R7KBF7ANCNFSM4PVHAGOQ .

-- Sent from mobile phone

aboutlo avatar Aug 06 '20 21:08 aboutlo

With Typescript 4.1, it might be possible to generate a typescript model from the JSON schema. If people are interested, check out this library (still in beta): https://github.com/RishabhJain96/json-schema-type

(Comment copied from https://github.com/fastify/fastify/issues/1668)

RishabhJain96 avatar Nov 22 '20 08:11 RishabhJain96

Some other art for types w/ fluent builder

https://github.com/sberan/typed-json-schema/tree/next

calebboyd avatar Jan 27 '21 02:01 calebboyd

Hi! please also check https://github.com/Coobaha/typed-fastify - very alpha release but works nicely :)

It requires TS ^4.2 and provides strongly typed handlers against defined schema and runtime validations by using generated json schema from types. It enforces developer to respond with status, headers and payload that are matching schema.

Small demo:

https://user-images.githubusercontent.com/2446638/108409543-08b45f00-722f-11eb-905c-06505b57f5fe.mp4

Coobaha avatar Feb 18 '21 19:02 Coobaha

Was thinking about using https://github.com/ThomasAribart/json-schema-to-ts but TypeBox seems a bit nicer option here since it gives concise API and all the autocompletes

misha-erm avatar Mar 03 '21 17:03 misha-erm