@okutils/json-d
v26.9.22
Published
JSON data types for TypeScript.
Readme
@okutils/json-d
General-purpose JSON types for TypeScript. Use them for API data, configuration, and other JSON data in frontend and Node.js projects when you don’t need to define the exact shape of an object. Unlike Record<string, any>, these types limit values to JSON-compatible types, including nested objects and arrays.
Installation
npm i @okutils/json-dUsage
This is a types-only package, so use import type:
Defining a JSON Object
import type { JSONObject } from "@okutils/json-d";
const user: JSONObject = {
id: 1,
name: "Xiaoming",
active: true,
avatar: null,
tags: ["TypeScript", "React"],
profile: {
city: "Shanghai",
settings: { darkMode: true },
},
};Reading Object Fields
import type { JSONObject } from "@okutils/json-d";
const getDisplayName = (user: JSONObject): string => {
const name = user.name;
return typeof name === "string" ? name.toUpperCase() : "Anonymous user";
};
getDisplayName({ name: "Alice" }); // "ALICE"
getDisplayName({ id: 1 }); // "Anonymous user"Fetching API Data in React
This example fetches a JSON object from /api/user.
import { useEffect, useState } from "react";
import type { JSONObject } from "@okutils/json-d";
export const Foo = () => {
const [data, setData] = useState<JSONObject | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const controller = new AbortController();
const fetchData = async () => {
try {
const response = await fetch("/api/user", {
signal: controller.signal,
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
const value: unknown = await response.json();
// A JSON response can also be an array, a scalar, or null.
if (
value === null ||
typeof value !== "object" ||
Array.isArray(value)
) {
throw new Error("Expected a JSON object from the API");
}
if (!controller.signal.aborted) {
setData(value as JSONObject);
}
} catch (error) {
if (!controller.signal.aborted) {
setError(error instanceof Error ? error.message : "Request failed");
}
}
};
void fetchData();
return () => controller.abort();
}, []);
if (error !== null) return <p role="alert">{error}</p>;
if (data === null) return <p>Loading…</p>;
const name = typeof data.name === "string" ? data.name : "Anonymous user";
return (
<section>
<h2>{name}</h2>
<pre>{JSON.stringify(data, null, 2)}</pre>
</section>
);
};Advanced Usage
Working with JSONScalar
Use JSONScalar for values that can be strings, numbers, booleans, or null:
import type { JSONScalar } from "@okutils/json-d";
const formatCell = (value: JSONScalar): string => {
if (value === null) return "—";
if (typeof value === "boolean") return value ? "Yes" : "No";
return String(value);
};
formatCell("Xiaoming"); // "Xiaoming"
formatCell(42); // "42"
formatCell(false); // "No"
formatCell(null); // "—"
// formatCell({ name: 'Xiaoming' }); // Type error: objects are not allowed
// formatCell(['TypeScript']); // Type error: arrays are not allowedWorking with JSONValue
Use JSONValue when your data can be any JSON value: a scalar, an object, or an array. For example, this browser utility saves JSON data to localStorage:
import type { JSONValue } from "@okutils/json-d";
const saveJSON = (key: string, value: JSONValue): void => {
localStorage.setItem(key, JSON.stringify(value));
};
saveJSON("theme", "dark");
saveJSON("pageSize", 20);
saveJSON("notifications", true);
saveJSON("selection", null);
saveJSON("user", { id: 1, name: "Xiaoming" });
saveJSON("recentUsers", [
{ id: 1, name: "Xiaoming" },
{ id: 2, name: "Xiaohong" },
]);
// Readonly arrays are supported too, including those created with `as const`.
saveJSON("coordinates", [121.47, 31.23] as const);