-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: use Record for properties field in Schema Object #135
base: master
Are you sure you want to change the base?
fix: use Record for properties field in Schema Object #135
Conversation
Hey @pjmolina, came across this issue while I was trying to iterate over the |
src/model/openapi31.ts
Outdated
@@ -292,7 +292,7 @@ export interface SchemaObject extends ISpecificationExtension { | |||
anyOf?: (SchemaObject | ReferenceObject)[]; | |||
not?: SchemaObject | ReferenceObject; | |||
items?: SchemaObject | ReferenceObject; | |||
properties?: { [propertyName: string]: SchemaObject | ReferenceObject }; | |||
properties?: Record<string, SchemaObject | ReferenceObject>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest : Record<string, SchemaObject | ReferenceObject | undefined>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the worst case, it'll be an empty object, which again is a valid SchemaObject
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@remidewitte do you think undefined
would be needed here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Properties assigned with undefined
are not exported to YAML and JSON at all.
console.log(
yaml.stringify({
property: undefined,
}),
);
console.log(
JSON.stringify({
property: undefined,
}),
);
{}
{}
Therefore, the only benefit for adding undefined
is for conditional properties:
yaml.stringify({
property: isIncluded() ? "something" : undefined
});
But that condition can be implemented differently, without involving undefined
at all:
yaml.stringify({
...(isIncluded() ? {property: "something"} : {})
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with noUncheckedIndexedAccess
enabled, @remidewitte
without it:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK excellent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, should I update the types to Partial<Record<string, SchemaObject | ReferenceObject>>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vaibhavrajsingh2001 , Taking into account the concept and the goal of this package:
TypeScript library to help building OpenAPI 3.x compliant API contracts.
I'd say: there are more benefits in Partial<>
than any harm.
Under the hood Partial<>
makes all properties optional ?:
, while does not explicitly welcome undefined
,
which can be assigned, but still there is no harm of that — it will not go further (JSON and YAML stringifiers remove it). It's helpful both for conditional writing and for avoiding runtime errors while reading, like in the @remidewitte 's case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the PR @RobinTail @remidewitte
I have contradicting feelings here:
To be honest, not sure if it is makes worthy. And if we are breaking uses cases for anyone else. |
Using mapped types like
{ [propertyName: string]: SchemaObject | ReferenceObject }
doesn't ensure the key to be of typestring
. Instead, TypeScript interprets the key asstring | number
.This behaviour can be verified in the following playground
Due to this issue, if you iterate over the properties of a schema, TypeScript can't be sure that the key is of type
string
. Instead the key will be interpreted as of typestring | number
.Using a
Record
allows to strictly type the key to only be of typestring
, which can be verified hereIt's a known TypeScript issue microsoft/TypeScript#48269