refactor: tighten nitro editor JSON typing with generic path helpers

This commit is contained in:
openhands committed 2026-08-09 12:38:30 +02:00
1 parent 6549ae1959
commit ca49c6b5a8
1 file changed
+12 -20
@@ -47,8 +47,7 @@ interface NitroVisualization {
}
// The .nitro metadata is untyped JSON from disk; typed only for the fields the
// editor reads/writes, with an index signature so the generic path helpers can
// traverse arbitrary nested keys.
// editor reads/writes. Unknown keys are traversed via the path helpers below.
interface NitroMetadata {
visualizationType?: string;
logicType?: string;
@@ -59,19 +58,18 @@ interface NitroMetadata {
};
};
visualizations?: NitroVisualization[];
[key: string]: unknown;
}
type JsonObject = Record<string, unknown>;
function updateNested<T extends JsonObject>(
function updateNested<T extends object>(
obj: T,
path: string,
value: unknown,
): T {
const clone: T = JSON.parse(JSON.stringify(obj));
const keys = path.split(".");
let current: JsonObject = clone;
let current: JsonObject = clone as JsonObject;
for (let i = 0; i < keys.length - 1; i++) {
const next = current[keys[i]];
if (!next || typeof next !== "object" || Array.isArray(next)) {
@@ -83,14 +81,14 @@ function updateNested<T extends JsonObject>(
return clone;
}
function getNested(obj: unknown, path: string, fallback?: unknown): unknown {
function getNested<T>(obj: unknown, path: string, fallback: T): T {
const keys = path.split(".");
let current: unknown = obj;
for (const key of keys) {
if (current == null || typeof current !== "object") return fallback;
current = (current as JsonObject)[key];
}
return current ?? fallback;
return current === undefined ? fallback : (current as T);
}
const ALL_DIRECTIONS = [0, 1, 2, 3, 4, 5, 6, 7];
@@ -255,14 +253,12 @@ export function NitroEditorDialog({
// ── Visual tab helpers ──
const dims = (
metadata
? getNested(metadata, "logic.model.dimensions", { x: 1, y: 1, z: 0 })
: { x: 1, y: 1, z: 0 }
) as { x: number; y: number; z: number };
const directions = (
metadata ? getNested(metadata, "logic.model.directions", [0]) : [0]
) as number[];
const dims = metadata
? getNested(metadata, "logic.model.dimensions", { x: 1, y: 1, z: 0 })
: { x: 1, y: 1, z: 0 };
const directions = metadata
? getNested(metadata, "logic.model.directions", [0])
: [0];
const setDim = (axis: "x" | "y" | "z", value: string) => {
const num =
@@ -271,11 +267,7 @@ export function NitroEditorDialog({
};
const toggleDirection = (dir: number) => {
const current = getNested(
metadata,
"logic.model.directions",
[0],
) as number[];
const current = getNested(metadata, "logic.model.directions", [0]);
const next = current.includes(dir)
? current.filter((d: number) => d !== dir)
: [...current, dir].sort((a: number, b: number) => a - b);