Skip to content

Conversation

@LinusU
Copy link
Collaborator

@LinusU LinusU commented Aug 13, 2018

This is very convenient for two things:

  1. When declaring your own functions that accepts a schema

  2. When putting a schema in a variable before passing it to createValidator, as without this the type information on string literals gets erased, and your schema will not be accepted as input:

Not working:

import createValidator = require('is-my-json-valid') // mySchema will have the type `{ type: string }`, which is not a valid Schema type const mySchema = { type: 'number' } // Error: Type `{ type: string }` is not assignable... createValidator(mySchema)

Working:

import createValidator = require('is-my-json-valid') const mySchema: createValidator.Schema = { type: 'number' } createValidator(mySchema)
@LinusU
Copy link
Collaborator Author

LinusU commented Aug 13, 2018

Hmmm, without existential types (microsoft/TypeScript#14466) this will have the same problem as we currently have with nested object properties.

Basically, this will only work well for primitive type schemas.

In use case 1, the problem will be that to get any meaningful return value that function will need to have all the same overloads that we are defining in our Factory interface.

In use case 2, the type will quickly be returned as never as this will only prevent the most top-level type widening to happen. Basically, adding only the ability to save primitive schemas in variables.

This could potentially be helped by exporting all of the different types of schemas, but that will just push much of the burden of doing workarounds (basically overloading) that we are doing internally, externally. I don't think that that is a good road to go down.

With that, I'm not sure it makes sense to merge this before existential types are fixed. I think that with that merged, we would be able to define a single Schema type, and also a single TypeToSchema<Schema> type that returns the parsed type...


Hmm, actually realised that I think the problem should come from type-erasing a specific schema into a generic Schema, which then obviously cannot be mapped into a type. But for some reason this works:

import createValidator = require('is-my-json-valid') const input = null as unknown const mySchema: createValidator.Schema = { type: 'number' } const myValidator = createValidator(mySchema) if (myValidator(input)) { // input is a number here }

Seems like the difference lies in const foo: Type = foobar() instead of const foo = foobar() as Type.

Hmmmm 🤔

@sirreal
Copy link

sirreal commented Aug 11, 2019

Do you have a recommended way forward for folks who want to type schemas? Can you elaborate the kind of issues we might hit?

There's a roundabout way to get to the inner schema type:

export function doSomethingWithSchemas( schema: Parameters< typeof import('is-my-json-valid') >[0] ) { /* … */ }

But I'd like to understand what the problem is with using this type, it's not immediately clear to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants