Proper way to declare JSON object in Typescript
Update: 7/26/2021
I revisited the discussion noted in the original answer, and there is now an update with an improved implementation.
type JSONValue =
| string
| number
| boolean
| null
| JSONValue[]
| {[key: string]: JSONValue}
interface JSONObject {
[k: string]: JSONValue
}
interface JSONArray extends Array<JSONValue> {}
This has been working very well for me.
Discussion reference: https://github.com/microsoft/TypeScript/issues/1897#issuecomment-822032151
Original answer: Sep 29 '20
I realize this is an old question, but I just found a solution that worked very well for me. Declare the following
type JsonPrimitive = string | number | boolean | null
interface JsonMap extends Record<string, JsonPrimitive | JsonArray | JsonMap> {}
interface JsonArray extends Array<JsonPrimitive | JsonArray | JsonMap> {}
type Json = JsonPrimitive | JsonMap | JsonArray
then any of the following (including the OP's version slightly modified for syntax errors) will work
let a: Json = {};
a[1] = 5;
a["abc"] = "abc";
a = {
a: {
a: 2,
},
b: [1, 2, 3],
c: true,
};
a = [
{
"id": 1,
"title": "something",
"node": [
{
"id": 1,
"title": "something",
"node": [],
},
],
},
{
"id": 2,
"title": "something",
"node": [
{
"id": 1,
"title": "something",
"node": [],
},
],
},
];
This answer should be credited to Andrew Kaiser who made the suggestion on the discussion about making Json a basic type in Typescript: https://github.com/microsoft/TypeScript/issues/1897#issuecomment-648484759
Here is an easy and naive implementation of what you're asking for:
interface IDataNode {
id: number;
title: string;
node: Array<IDataNode>;
}
If you want to instantiate said nodes from code:
class DataNode implements IDataNode {
id: number;
title: string;
node: Array<IDataNode>;
constructor(id: number, title: string, node?: Array<IDataNode>) {
this.id = id;
this.title = title;
this.node = node || [];
}
addNode(node: IDataNode): void {
this.node.push(node);
}
}
Using this to hardcode your structure:
let data: Array<IDataNode> = [
new DataNode(1, 'something', [
new DataNode(2, 'something inner'),
new DataNode(3, 'something more')
]),
new DataNode(4, 'sibling 1'),
new DataNode(5, 'sibling 2', [
new DataNode(6, 'child'),
new DataNode(7, 'another child', [
new DataNode(8, 'even deeper nested')
])
])
];