refactor: remove any types from nitro editor dialog

This commit is contained in:
openhands committed 2026-08-09 12:27:13 +02:00
1 parent 4993b75608
commit 6549ae1959
1 file changed
+48 -25
@@ -39,28 +39,56 @@ interface NitroEditorDialogProps {
onOpenChange: (open: boolean) => void;
}
// Keep these helpers on `any` — Next's build-time checker has repeatedly
// disagreed with `tsc` on stricter JSON typings for this editor.
// biome-ignore lint/suspicious/noExplicitAny: metadata tree is untyped JSON
function updateNested(obj: any, path: string, value: unknown): any {
const clone = JSON.parse(JSON.stringify(obj));
interface NitroVisualization {
size?: number;
layers?: Record<string, { z?: number; alpha?: number; ink?: string }>;
colors?: Record<string, Record<string, { color: number }>>;
animations?: Record<string, unknown>;
}
// 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.
interface NitroMetadata {
visualizationType?: string;
logicType?: string;
logic?: {
model?: {
dimensions?: { x: number; y: number; z: number };
directions?: number[];
};
};
visualizations?: NitroVisualization[];
[key: string]: unknown;
}
type JsonObject = Record<string, unknown>;
function updateNested<T extends JsonObject>(
obj: T,
path: string,
value: unknown,
): T {
const clone: T = JSON.parse(JSON.stringify(obj));
const keys = path.split(".");
let current = clone;
let current: JsonObject = clone;
for (let i = 0; i < keys.length - 1; i++) {
if (!current[keys[i]]) current[keys[i]] = {};
current = current[keys[i]];
const next = current[keys[i]];
if (!next || typeof next !== "object" || Array.isArray(next)) {
current[keys[i]] = {};
}
current = current[keys[i]] as JsonObject;
}
current[keys[keys.length - 1]] = value;
return clone;
}
// biome-ignore lint/suspicious/noExplicitAny: metadata tree is untyped JSON
function getNested(obj: any, path: string, fallback?: unknown): any {
function getNested(obj: unknown, path: string, fallback?: unknown): unknown {
const keys = path.split(".");
let current = obj;
let current: unknown = obj;
for (const key of keys) {
if (current == null || typeof current !== "object") return fallback;
current = current[key];
current = (current as JsonObject)[key];
}
return current ?? fallback;
}
@@ -99,10 +127,9 @@ export function NitroEditorDialog({
open,
onOpenChange,
}: NitroEditorDialogProps) {
// biome-ignore lint/suspicious/noExplicitAny: explicitly chosen here, see surrounding code
const [metadata, setMetadata] = useState<any>(null);
// biome-ignore lint/suspicious/noExplicitAny: explicitly chosen here, see surrounding code
const [originalMetadata, setOriginalMetadata] = useState<any>(null);
const [metadata, setMetadata] = useState<NitroMetadata | null>(null);
const [originalMetadata, setOriginalMetadata] =
useState<NitroMetadata | null>(null);
const [jsonText, setJsonText] = useState("");
const [loading, setLoading] = useState(false);
const [saving, setSaving] = useState(false);
@@ -120,10 +147,9 @@ export function NitroEditorDialog({
const [jsonError, setJsonError] = useState<string | null>(null);
const patchMeta = (path: string, value: unknown) => {
// Explicit any avoids noImplicitAny on updater params and dodges
// Next build's stricter JSON inference that disagreed with tsc.
// biome-ignore lint/suspicious/noExplicitAny: metadata tree is untyped JSON
setMetadata((prev: any) => updateNested(prev, path, value));
setMetadata((prev) =>
prev == null ? prev : updateNested(prev, path, value),
);
};
const fetchMetadata = useCallback(async () => {
@@ -258,12 +284,9 @@ export function NitroEditorDialog({
};
// Get visualization with size=64 for layer/color editing
// biome-ignore lint/suspicious/noExplicitAny: explicitly chosen here, see surrounding code
const viz64 = metadata?.visualizations?.find((v: any) => v.size === 64);
const viz64 = metadata?.visualizations?.find((v) => v.size === 64);
const viz64Index =
metadata?.visualizations?.findIndex(
(v: { size: number }) => v.size === 64,
) ?? -1;
metadata?.visualizations?.findIndex((v) => v.size === 64) ?? -1;
const layerCount = viz64?.layers ? Object.keys(viz64.layers).length : 0;
const colorCount = viz64?.colors ? Object.keys(viz64.colors).length : 0;