-
Notifications
You must be signed in to change notification settings - Fork 419
Description
This is all based around an attempt to resolve issues like #201, #210, etc
Currently, j2t generates definitions that are not strict mode compatible:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"myProp": {
"type": "string"
}
},
"additionalProperties": {
"type": "string"
}
}
results in
/* tslint:disable */
/**
* This file was automatically generated by json-schema-to-typescript.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run json-schema-to-typescript to regenerate this file.
*/
export interface Foo {
myProp?: string;
[k: string]: string;
}
This isn't valid under strict
, specifically due to strictNullChecks
.
To be valid, | undefined
needs to be explicitly added.
The "downside" to this is that you have to guard against undefined
:
interface Mx {
[k: string]: string | undefined;
}
const o: Mx = {};
o.myProp.toUpperCase();
// ^^ Error:(53, 1) TS2532: Object is possibly 'undefined'.
for (const key in o) {
o[key].toUpperCase();
// ^^ Error:(57, 3) TS2532: Object is possibly 'undefined'.
}
Personally, I actually think this is for the better anyway, given that since you're not requiring myProp
, it could very well be undefined.
This isn't actually a breaking change, since this will only affect code that has strictNullChecks
, but if strictNullChecks
is on, generated definitions would stop compiling anyway, making it a catch-22 😄
The implementation on how to support this is the big question - For package.json
, the fix is easy: use tsType
, but the problem w/ this is it's a complete override, which means its brittle:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"myProp": {
"type": "string"
}
},
"definitions": {
"myDef": {
"type": "string"
}
},
"additionalProperties": {
"$ref": "#/definitions/myDef",
"tsType": "undefined"
}
}
Desired:
export type MyDef = string;
export interface Foo2 {
myProp?: string;
[k: string]: MyDef | undefined;
}
Actual:
export interface Foo {
myProp?: string;
[k: string]: undefined;
}
Hence, ideally, what we need is a way to append types; I don't really see much of a use-case outside of appending undefined, so I'd be happy w/ something like "tsCanBeUndefined": true
.
Alternatively, a solution that is a bit nicer but more breaking (IMO) would be whenever an interface is generated w/ an index type (other than any
), to add | undefined
if the interface has any optional properties.