Skip to content
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

JSON and LosslessNumber types #245

Open
josdejong opened this issue Nov 22, 2022 · 0 comments
Open

JSON and LosslessNumber types #245

josdejong opened this issue Nov 22, 2022 · 0 comments

Comments

@josdejong
Copy link
Owner

From #244:

I was disappointed that LosslessNumber instance of Number is false, also I get weird type errors from lossless-json, I had to add an any (d is a string):

      const dataAsLosslessJson = losslessJsonParse(d);
      jsonDataString = "json_data = " + objToPython(dataAsLosslessJson as any) + "\n";

if I remove the as any, I get a type error from objToPython saying Argument of type 'unknown' is not assignable to parameter of type 'string | number | boolean | object | null'. ts(2345). Why does it think dataAsLosslessJson is unknown?

I'm a bit struggling with defining types for the library. For example the native JSON.parse is in my IDE giving the following TypeScript types:

interface JSON {
  parse(text: string, reviver?: (this: any, key: string, value: any) => any): any;
}

Which is quite generic.

We can define JSON like:

export type JSONPrimitive = string | number | boolean | null
export type JSONValue =
| { [key: string]: JSONValue } // object
| JSONValue[] // array
| JSONPrimitive
export type JSONObject = { [key: string]: JSONValue }
export type JSONArray = JSONValue[]

But as soon as we have a reviver and/or numberParser, the output can be sort of anything. I tried to represent this as:

export type JavaScriptPrimitive = string | number | boolean | null | bigint | Date | unknown
export type JavaScriptValue =
| { [key: string]: JavaScriptValue } // object
| JavaScriptValue[] // array
| JavaScriptPrimitive
export type JavaScriptObject = { [key: string]: JavaScriptValue }
export type JavaScriptArray = JavaScriptValue[]

So, there are two different levels of JSON, but what types can really come out of the function depend on the reviver and numberParser. Maybe with generics it is possible to define this strictly instead of relying on unknown (which covers LosselessNumber and anything).

Now, as for your specific questions and ideas:

  1. The output of LosslessJSON.parse() is a JavaScriptValue. Your function objToPython(obj: string | number | boolean | object | null, indent = 0) does not accept the more broad definition of JavaScriptValue so it makes sense that TypeScript complains about that. I guess the logic solution is to make the first argument of objToPython compatible with JavaScriptValue. Or we have to be able to
  2. It is an interesting idea to make LosslessNumber extend Number. I have to think that through a bit. It would make the wrapper class less lightweight: we would have to add all methods that Number has. But it can make usage more natural, and maybe we could make JSON.parse return JSONValue instead of JavaScriptValue somehow 🤔
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant