You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
But how useful would that be? I think most code wouldn't want a structure like this, unless you wrote a library that was specifically for making modifications on the structure of any JSON. In most realistic use cases, you're going to want to cast the return of JSON.parse to a type specific for your application, probably using runtime checks and type guards along the way. In those cases you want any or maybe unknown (see #26188)
But how useful would that be? I think most code wouldn't want a structure like this, unless you wrote a library that was specifically for making modifications on the structure of any JSON. In most realistic use cases, you're going to want to cast the return of JSON.parse to a type specific for your application, probably using runtime checks and type guards along the way. In those cases you want any or maybe unknown
As mentioned in #26188 and several other places, returning any from JSON.parse is not correct. According to the spec and the practice JSON.parse returns a more specialized range of types than any implies - it's even more specialized than unknown implies when there is no reviver function.
To be clear: JSON.parse(string) cannot and will not ever return a Buffer, Error, or any such data structures. Thus we can make SOME assumptions about its output. That said, adding a reviver function breaks the rule and I don't see a way to infer the resulting data structure.
To handle all this we could have two signatures for JSON.parse:
JSON.parse(text: string): JsonType - Parses a stringified JSON value into a JSON data structure. The user may want to specialize the output, and they can via casting and checks, but the default is now at least clear and correct.
JSON.parse(text: string, reviver: (key: string, value: JsonType) => unknown): unknown - Parses a stringified JSON value, but makes no assumptions about the structure of the output since the reviver could mangle the output types in many different ways.
JsonType is defined based on the JSON spec, and there are several well-stated type unions that express the concept.
Some may be frustrated by the compiler telling them that they really don't know the type returned. That's understandable: all of us had to unlearn bad habits when we went from JavaScript to TypeScript.
All that said, I'd REALLY appreciate JSON.parse returning unknown rather than any if the more complex JSON types are too mush - after all that's WHY I choose TypeScript over raw JavaScript: the former gives me a layer of type safety that yells at me in the compiler if I do something stupid. As it stands JSON.parse('[]').notexist is a runtime error instead of a compiler error.
Yes this would be a breaking change. But a welcome one. It could also be behind a flag like the change to catch so that it could be introduced in a minor version.
As an aside, the project ts-reset provides a quick hack workaround/prototype of some of this plus a few other cases. However its opt-in mechanism means that it can't be used in libraries. 😢
Activity
Bnaya commentedon Sep 10, 2018
Maybe unknown is more correct
nmain commentedon Sep 10, 2018
Assuming no
receiverparameter was passed, you could express it more exactly using something like this (which has been proposed before, I think):But how useful would that be? I think most code wouldn't want a structure like this, unless you wrote a library that was specifically for making modifications on the structure of any JSON. In most realistic use cases, you're going to want to cast the return of
JSON.parseto a type specific for your application, probably using runtime checks and type guards along the way. In those cases you wantanyor maybeunknown(see #26188)RyanCavanaugh commentedon Sep 10, 2018
This is exactly correct
kf6kjg commentedon Feb 23, 2023
As mentioned in #26188 and several other places, returning any from
JSON.parseis not correct. According to the spec and the practiceJSON.parsereturns a more specialized range of types thananyimplies - it's even more specialized thanunknownimplies when there is no reviver function.To be clear:
JSON.parse(string)cannot and will not ever return a Buffer, Error, or any such data structures. Thus we can make SOME assumptions about its output. That said, adding a reviver function breaks the rule and I don't see a way to infer the resulting data structure.To handle all this we could have two signatures for
JSON.parse:JSON.parse(text: string): JsonType- Parses a stringified JSON value into a JSON data structure. The user may want to specialize the output, and they can via casting and checks, but the default is now at least clear and correct.JSON.parse(text: string, reviver: (key: string, value: JsonType) => unknown): unknown- Parses a stringified JSON value, but makes no assumptions about the structure of the output since the reviver could mangle the output types in many different ways.JsonTypeis defined based on the JSON spec, and there are several well-stated type unions that express the concept.Some may be frustrated by the compiler telling them that they really don't know the type returned. That's understandable: all of us had to unlearn bad habits when we went from JavaScript to TypeScript.
All that said, I'd REALLY appreciate
JSON.parsereturningunknownrather thananyif the more complex JSON types are too mush - after all that's WHY I choose TypeScript over raw JavaScript: the former gives me a layer of type safety that yells at me in the compiler if I do something stupid. As it standsJSON.parse('[]').notexistis a runtime error instead of a compiler error.Yes this would be a breaking change. But a welcome one. It could also be behind a flag like the change to catch so that it could be introduced in a minor version.
As an aside, the project
ts-resetprovides a quick hack workaround/prototype of some of this plus a few other cases. However its opt-in mechanism means that it can't be used in libraries. 😢