TS is not able to infer that an optional field might be undefined
See original GitHub issueWhat version of Ajv are you using?
v8.11.2 ( latest )
Your typescript code
import Ajv, { JSONSchemaType } from "ajv";
interface MyType {
myProp?: OtherType;
}
interface OtherType {
foo: string;
bar: number;
}
const otherSchema: JSONSchemaType<OtherType> = {
type: 'object',
properties: {
foo: { type: 'string', minLength: 1 },
bar: { type: 'number' },
},
required: ['foo', 'bar'],
additionalProperties: false
};
const mySchema: JSONSchemaType<MyType> = {
type: 'object',
properties: {
myProp: otherSchema,
},
required: [],
additionalProperties: false,
};
Typescript compiler error messages
app.ts:22:7 - error TS2322: Type '{ type: "object"; properties: { myProp: { type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; unevaluatedProperties?: boolean | ... 1 more ... | undefined; ... 7 more ...; maxProperties?: number | undefined; } & { ...; } & { ...; } & { ...; }; }; required: never[]; a...' is not assignable to type 'UncheckedJSONSchemaType<MyType, false>'.
The types of 'properties.myProp' are incompatible between these types.
Type '{ type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; unevaluatedProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; ... 7 more ...; maxProperties?: number | undefined; } & { ...; } & { ...; } & { ...; }' is not assignable to type '{ $ref: string; } | (UncheckedJSONSchemaType<OtherType | undefined, false> & { nullable: true; const?: null | undefined; enum?: readonly (OtherType | null | undefined)[] | undefined; default?: OtherType | ... 1 more ... | undefined; })'.
Type '{ type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; unevaluatedProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; ... 7 more ...; maxProperties?: number | undefined; } & { ...; } & { ...; } & { ...; }' is not assignable to type '{ $ref: string; }'.
Types of property '$ref' are incompatible.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
Describe the change that should be made to address the issue?
I’m not sure but I think this error occurs because TS doesn’t know that myProp
in mySchema
might be undefined. The required array does not contain myProp
.
I could try to assign { nullable: true }
to myProp
but there is no field for schema
so this is not possible
myProp: { schema: otherSchema, nullable: true }
Are you going to resolve the issue?
Unfortunately I don’t know how.
Issue Analytics
- State:
- Created 9 months ago
- Comments:5 (2 by maintainers)
Top Results From Across the Web
Why doesn't typescript undefined type behave same as ...
It won't compile because property bar is missing. But we say that it can be undefined, which will work if we explicitly set...
Read more >How to Deal with Optional Things and "Undefined" in TypeScript
Working with JavaScript means working with undefined . It's a standard way to say, “This thing you asked for doesn't exist.”.
Read more >TypeScript - Sequelize
'CreationOptional' is a special type that marks the field as optional ... Note that attributes that accept null , or undefined do not...
Read more >Distinguish missing and undefined · Issue #13195 - GitHub
I have met JavaScript libraries that used 'prop' in options or options.hasOwnProperty('prop') to check for the presence of an option, and then ...
Read more >Documentation - TypeScript 2.0
TypeScript has two special types, Null and Undefined, that have the values null and undefined respectively. Previously it was not possible to explicitly ......
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I am not an authority on that… There is usually some difference between the types that are convenient for your application (e.g., not allow nulls, as it’s an object in JS) and the types that are convenient for the API, as it is just JSON and other languages call it… So in some cases it’s convenient to have types that fit API definition (that is to allow null) and treat it in the application correctly, and in some cases you may end up having some API-facing types that get “parsed” (transformed) into some more narrow internal types.
I very much agree with “parse don’t validate” philosophy (which is somewhat ironic), so I’ve been using JTD for quite some time, and not JSON schema, as it doesn’t support “parsing” approach, being mostly incompatible with type systems…
There is definitely an argument to challenge that decision (that optional properties must be nullable in JSON) and either revise it in the next major version or make it optional, but the number of various options is very large already, so not sure…
I also find it weird that
nullable
is required for optional fields, I’ve been migrating to TS and an otherwise very long valid schema, I need to addnullable
almost everywhere ortype
or emptyrequired
in some very specific places that you can only find in a very hard to read error message…There is the same issue with the
required
field on objectsBut clearly those properties are not required as this doesn’t seem to change anything in the behavior of the validation (eg: required is by default empty, nullable is by default true)
Edit - another one: using
instanceOf
requires thetype: 'object'
to be defined, which should be inferred by the usage ofinstanceOf
Makes it too cumbersome to convert to TS