fix: narrow several from any type assertions in opencode core#22926
Merged
kitlangton merged 1 commit intodevfrom Apr 16, 2026
Merged
fix: narrow several from any type assertions in opencode core#22926kitlangton merged 1 commit intodevfrom
from any type assertions in opencode core#22926kitlangton merged 1 commit intodevfrom
Conversation
Starting to address the 107 'Unsafe assertion from any' sites flagged by
oxlint's typescript/no-unsafe-type-assertion rule. Focused on real
laundering of any values into typed values, rather than inline-typed
`.json() as {...}` patterns (which the rule still flags but are fine).
- util/filesystem.ts: change `readJson<T = any>` default to `readJson<T = unknown>` so callers must opt into a type
- npm/index.ts: add PackageJson type for readJson callers
- cli/cmd/tui/context/kv.tsx, test/config/config.test.ts: pass explicit type params to readJson
- cli/error.ts: narrow `data?.suggestions` and `data?.issues` via Array.isArray instead of casting (defensive: preserves behavior when underlying error shape has wrong type)
- lsp/lsp.ts: type workspaceSymbol's sendRequest and drop intermediate `as any`s on .then callbacks
- provider/provider.ts: narrow options?.workflowRef / options?.workflowDefinition via typeof check rather than casting from Record<string, any>
- session/session.ts: use `Number(...)` coercion instead of `as number` on the Anthropic/Bedrock/Vertex cache token fallback chain (safe() already handles NaN)
- tool/tool.ts: change Context.extra from { [k: string]: any } to { [k: string]: unknown } \u2014 downstream casts become 'more narrow' (still warns but stops laundering any)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First pass at the 107 "Unsafe assertion from any" sites flagged by oxlint's
typescript/no-unsafe-type-assertionrule. These are the most dangerous casts because they silently launder untyped values into typed ones.Strategy: focus on real laundering of
anyvalues, not inline-typed.json() as {...}patterns (lint still flags those, but they're fine — they annotate the expected API shape).Not enabling the rule yet — this is a down payment on a larger cleanup.
Changes
util/filesystem.ts— changereadJson<T = any>default toreadJson<T = unknown>. Callers must now opt into a concrete type or handleunknown, which means a value parsed from a JSON file can't silently satisfy any shape.npm/index.ts— add aPackageJsontype forreadJsonsopkg.dependenciesetc. are typed instead ofany.cli/cmd/tui/context/kv.tsx,test/config/config.test.ts— pass explicit type params toreadJsonat the call sites.cli/error.ts— replacedata?.suggestions as string[] | undefinedanddata?.issues as Array<...>withArray.isArray(...) ? ... : []narrowing. Defensive: now behaves correctly (returns empty array) if the underlying error payload has the wrong shape.lsp/lsp.ts— typeclient.connection.sendRequest<Symbol[]>("workspace/symbol", ...)and drop the intermediateas anyannotations on the.thencallbacks; returnresults.flat()directly instead ofas Symbol[].provider/provider.ts— narrowoptions?.workflowRef/options?.workflowDefinitionviatypeof === "string"instead of casting the values out ofRecord<string, any>.session/session.ts— replace(... ?? 0) as numberon the Anthropic/Bedrock/Vertex cache token fallback chain withNumber(...)coercion. The existingsafe()wrapper already handles NaN.tool/tool.ts— changeContext.extrafrom{ [key: string]: any }to{ [key: string]: unknown }. Downstream casts likectx.extra?.promptOps as TaskPromptOpsnow become "more narrow" warnings instead of "from any" errors.Impact
Unsafe assertion from anyin opencode src: 29 → 25 (4 fixed).no-unsafe-type-assertionacross the repo: 1079 → 1073 errors.Most of the remaining "from any" sites in opencode src are
.json() as {...}inline-type annotations for fetch responses, which is a reasonable pattern the lint will always flag. Future passes could add runtime schema validation for the most critical ones (well-known config, model registries, etc.).Verification
bun turbo typecheckpasses (all 13 tasks).bun run lintpasses (oxlint warnings only, no errors).bun test test/config/config.test.tspasses (73 tests, touches the updated readJson call).