ThomasAribart / json-schema-to-ts

Infer TS types from JSON schemas 📝
MIT License
1.4k stars 30 forks source link

$ref on definition and additionalProperties: false together results to never type #188

Open tothdanielax opened 5 months ago

tothdanielax commented 5 months ago

I try to refer to a definition and after that make additionalProperties: false. The expected result would be a TS type without [x: string]: unknown;

Simplified example:


export const ciSchemaa = {
    type: "object",
    $defs: {
        ciBaseMetadata: {
            type: "object",
            properties: {
                ciId: {
                    type: "string",
                },
            },
            required: [
                "ciId",
            ]
        },
    },
    $ref: "#/$defs/ciBaseMetadata",
    additionalProperties: false
} as const satisfies JSONSchema;

export type Ci = FromSchema<typeof ciSchema> // never

It is possible to make it work if I already set additionalProperties:false in the definition, but curious if that could be done as the last step.

mrl5 commented 1 month ago

I think it's just a matter of unhydrated $ref. It's mentioned in docs https://github.com/ThomasAribart/json-schema-to-ts?tab=readme-ov-file#references

tested with typescript =5.4.5 and json-schema-to-ts =3.1.0

At least in my example:

import type { FromSchema, JSONSchema } from 'json-schema-to-ts';

export const healthCode = {
    $id: 'HealthCode',
    type: 'string',
    enum: ['healthy', 'degraded'],
} as const satisfies JSONSchema;

export const healthRes = {
    type: 'object',
    properties: {
        code: {
            $ref: 'HealthCode#',
        },
    },
    required: ['code'],
    additionalProperties: false,
} as const satisfies JSONSchema;

export type HealthRes = FromSchema<typeof healthRes;

const h: HealthRes = {}; // Type '{}' is not assignable to type 'never'.

all I need to do to make it working is to hydrate the ref like this:

- export type HealthRes = FromSchema<typeof healthRes;
+ export type HealthRes = FromSchema<typeof healthRes, { references: [typeof healthCode] }>;