Reputation: 1046
I gather that this may be impossible, given that the return type of the even the native JSON.parse
function is any
, but I've been puzzling over how to create a generic JSON type interface in TypeScript. There's a solution on GitHub that comes extremely close:
type JSONValue = boolean | number | string | JSONObject | JSONArray
interface JSONObject {
[k: string]: JSONValue
}
interface JSONArray extends Array<JSONValue> {}
const json: JSONObject = {}
console.log(json.gray[9])
...but fails to compile in strict mode:
~ ❯❯❯ tsc --strict test.ts
test.ts(11,13): error TS7017: Element implicitly has an 'any' type because type 'JSONValue' has no index signature.
My understanding is that because JSONObject
and JSONArray
have index values, the union type JSONValue
should accept one as well; clearly the compiler disagrees. I'm curious for my own edification whether there's any way around this; given that the GitHub issue was from 2015, maybe TypeScript has changed in the interim.
Thanks for any thoughts from more seasoned script typers!
Upvotes: 4
Views: 2924
Reputation: 73788
type JsonObject = { [key: string]: JsonValue };
type JsonValue =
| null
| boolean
| number
| string
| JsonValue[]
| JsonObject;
const stringify = (subject: JsonObject) => {};
stringify({
foo: 'bar',
});
stringify({
// @ts-expect-error
foo: () => {}
});
Upvotes: 4