0

Why does the following snippet not compile, and how is the ES6 JSON interface supposed to be used?

let myVar: JSON = {"id": "12"};

Gives the following error message: Type '{ id: string; }' is not assignable to type 'JSON'. Object literal may only specify known properties, and '"id"' does not exist in type 'JSON'.

My IDE gives the following definition for JSON, but I can’t understand it:

interface JSON {
    readonly [Symbol.toStringTag]: string;
}
kotchwane
  • 2,082
  • 1
  • 19
  • 24
  • 1
    `JSON` is a reserved name already in use (by the object that provides `JSON.parse`). Use some other name. Note that JSON is simply a string until it is parsed, then it is an object. – Heretic Monkey May 04 '22 at 11:56
  • Does this answer your question? [How do I initialize a TypeScript Object with a JSON-Object?](https://stackoverflow.com/questions/22885995/how-do-i-initialize-a-typescript-object-with-a-json-object) – Heretic Monkey May 04 '22 at 11:58
  • If you are looking for a `type` to enforce an object to be compatible with JSON (by containing only primitves/arrays/objects) this [answer](https://stackoverflow.com/q/57858862/8613630) may help you. – Tobias S. May 04 '22 at 11:59
  • Aside, I'd use numbers for numbers, also in JSON, `'{"id": 12}'`. – Arjan May 04 '22 at 12:04
  • The interrogation stemmed from looking for a (native)JSON type in Typescript, and the best answer I could find on the subject was this one: [TypeScript - How to model a JSON object](https://stackoverflow.com/a/63085332/9450152) But my question remained after that, I couldn’t understand what this JSON interface was. The answers now clarify this! – kotchwane May 04 '22 at 12:38

2 Answers2

3

JSON is a global object defined by the JS specification designed to hold the parse and stringify methods for converting between JS data structures and JSON texts.

It isn't a type. It isn't supposed to be used as one.


When creating a custom object format, you are supposed to define your own type (although it isn't useful to do so here, but might be if you define a function elsewhere that you need to pass the object to as an argument). When dealing with JSON, you are dealing with strings.

type MyFormat = {
    id: string;
}

let myVar: MyFormat = {"id": "12"};
let myJSON: string = JSON.stringify(myVar);
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Aside, I'd use numbers for numbers, also in JSON, `{"id": 12}`. (Just confused by "When dealing with JSON, you are dealing with strings" while later I saw the `"12"` was taken from the question.) – Arjan May 04 '22 at 12:02
  • 1
    @Arjan — So would I, but I wasn't going to complicate matters by redesigning the OP's data structure in my answer. – Quentin May 04 '22 at 12:03
3

There's no reason you'd use the JSON interface in your code. It relates to the JSON built-in object, and there's no reason to use that object other than using its parse and/or stringify methods to parse or create JSON text.

From your code, you appear to misunderstand what JSON is. (Lots of people do! :-) ) JSON is a textual notation for data exchange. (More here.) If you're dealing with JavaScript or TypeScript source code, and not dealing with a string, you're not dealing with JSON.

Your myVar refers to an object. There's no need to put a type annotation on it, you can just let TypeScript infer it from the initializer, but if you wanted to put a type annotation on it you'd use either {id: string;} or Record<string, string> or some other object type:

// Letting TypeScript infer
let myVar = {"id": "12"};
// Or specify an object with an `id` property of type string
let myVar: {id: string;} = {"id": "12"};
// Or create a type alias and use it
type MyVarType = {
    id: string;
};
let myVar: MyVarType = {"id": "12"};
// Or perhaps an object where any string is a valid property name and the types are all strings
let myVar: Record<string, string> = {"id": "12"};

See the documentation linked above for more about object types.


Side note: If you meant to use a number for id, you'd use id: number or similar:

let myVar: {id: number;} = {id: 12};
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875