type-fest
type-fest copied to clipboard
Make `JsonObject` work as expected with TS 4.4 `--exactOptionalPropertyTypes`
#269 brought to my attention that #65 changed the JsonObject
so that all keys are marked as optional.
Before TypeScript 4.4 a { foo?: string}
and a { foo?: string|undefined }
was always treated as equal, so #65 made sense then.
But with TS 4.4 the new --exactOptionalPropertyTypes
config was introduced, which (correctly )no longer treats { foo?: string}
as equal to { foo?: string|undefined }
.
For some reason though, the change introduced in #65 still gets treated in the old way: https://github.com/sindresorhus/type-fest/blob/6b6d81ce894517268391db63b3d6538e971c8126/source/basic.d.ts#L22
I would propose reverting #65 and moving back to:
export type JsonObject = {[key: string]: JsonValue};
I think it behaves more correctly, as can be seen in this playground.
I would propose reverting #65 and moving back to:
👍
Since this style of JsonObject
has been out for so long, I think we should maybe split it up into two types (names for illustration purposes only) to not break things unnecessarily:
-
JsonObjectStringifiable
– one that behaves like today'sJsonObject
. Would represent a value intended forJSON.stringify()
where{ foo: undefined }
and plain{}
are functionally equivalent. -
JsonObjectParsed
– one that represents an actual parsed JSON value, coming from eg.JSON.parse()
whereundefined
as a value is impossible.
Relatedly:
JSON.stringify(['foo', 1, undefined, 2])
Outputs:
["foo",1,null,2]
So I guess JsonArray
should also really have a one type focused on serialization/stringification and another that properly reflects the values available in the JSON itself.
(If one wants to go crazy, then such serialization/stringification versions of the types could even include support for the toJSON
method on objects)
I would propose reverting #65 and moving back to:
export type JsonObject = {[key: string]: JsonValue};
FI: A version that supports both cases (playground) added in #465.
export type JsonObject = {[Key in string]: JsonValue} & {[Key in string]?: JsonValue | undefined};