fix(lint): enable anti-slop/no-unknown-type-aliases (#20784)

Flips anti-slop/no-unknown-type-aliases from "off" to "error" and fixes the
3 baseline violations.

The rule rejects a named type alias whose resolved type is `unknown` (directly,
through another alias, through parentheses, or as a member of a union). Such an
alias is strictly worse than writing `unknown`: it reads like a real domain type
at every use site while accepting anything, so the compiler stops helping and
readers are actively misled. `unknown` is fine, but it must stay visible at the
boundary that actually parses it.

Violations fixed (3 at baseline, 5 source files touched):

- src/main/runtime/workspace-session-failed-write-rollback.ts
  `type RollbackValue = unknown` -> a real recursive JSON-shaped union
  `RollbackSlot` (primitives | null | undefined | typeof MISSING |
  readonly RollbackSlot[] | RollbackRecord), with a named
  `type RollbackRecord = { readonly [key: string]: RollbackSlot }`.
  The record is a named alias rather than an inline index signature because
  inline violates typescript/consistent-indexed-object-style, `interface`
  violates consistent-type-definitions, and `Readonly<Record<..>>` trips
  TS2456 circular-reference. The named alias satisfies all three.

- src/renderer/src/hooks/direct-ssh-reconnect-coordinator-types.ts
  `type DirectSshReconnectTimer = unknown` -> `ReturnType<typeof setTimeout>`,
  the handle that actually flows. `DirectSshReconnectTargetState.timer` is
  widened to `DirectSshReconnectTimer | null` to match the state machine, which
  initializes to null and resets to null in the scheduled callback.

- src/renderer/src/hooks/direct-ssh-host-hydration.ts
  `type HostReadTimer = unknown` -> `ReturnType<typeof setTimeout>`.

Fix pattern throughout: replace the alias with the type that already flows
through the code, never with `any` and never with a relabelled `unknown`.
Because the timer aliases are now honest, two pre-existing
`as ReturnType<typeof setTimeout>` casts at the clearTimeout boundaries could be
deleted, a net win under the repo's type-assertion policy.

Suppressions added: none. No eslint-disable, oxlint-disable, `any`, or `as`
cast was introduced anywhere in this change.

The diff is type-annotation-only; no runtime statement changed.
This commit is contained in:
Neil
2026-09-15 00:02:04 -07:00
committed by GitHub
parent 3ec6193e0f
commit c9ae17fe3d
6 changed files with 25 additions and 15 deletions
+1 -1
View File
@@ -38,7 +38,7 @@
"anti-slop/no-shape-in-symbol-names": "off",
"anti-slop/no-unknown-parameters": "off",
"anti-slop/no-unknown-returns": "off",
"anti-slop/no-unknown-type-aliases": "off",
"anti-slop/no-unknown-type-aliases": "error",
"anti-slop/no-unsafe-dictionary-type": "off",
"anti-slop/no-widen-then-assert": "error",
"anti-slop/require-readable-spacing": "off",
@@ -2,9 +2,21 @@ import { isDeepStrictEqual } from 'node:util'
import type { WorkspaceSessionState } from '../../shared/workspace-session-state-types'
const MISSING = Symbol('missing')
type RollbackValue = unknown
function isRecord(value: RollbackValue): value is Record<string, unknown> {
/** A JSON-shaped slot of persisted session state, or the absent-key sentinel. */
type RollbackSlot =
| string
| number
| boolean
| null
| undefined
| typeof MISSING
| readonly RollbackSlot[]
| RollbackRecord
type RollbackRecord = { readonly [key: string]: RollbackSlot }
function isRecord(value: RollbackSlot): value is RollbackRecord {
return (
value !== MISSING &&
typeof value === 'object' &&
@@ -15,10 +27,10 @@ function isRecord(value: RollbackValue): value is Record<string, unknown> {
}
function rollbackValue(
original: RollbackValue,
staged: RollbackValue,
current: RollbackValue
): RollbackValue {
original: RollbackSlot,
staged: RollbackSlot,
current: RollbackSlot
): RollbackSlot {
if (isDeepStrictEqual(original, staged)) {
return current
}
@@ -29,7 +41,7 @@ function rollbackValue(
return current
}
let changed = false
const next: Record<string, unknown> = { ...current }
const next: Record<string, RollbackSlot> = { ...current }
for (const key of new Set([
...Object.keys(original),
...Object.keys(staged),
@@ -18,7 +18,7 @@ import { directSshAuthoritiesEqual } from './direct-ssh-reconnect-tokens'
export const DIRECT_SSH_HOST_READ_TIMEOUT_MS = 5_000
type HostReadTimer = unknown
type HostReadTimer = ReturnType<typeof setTimeout>
export type DirectSshHostHydrationDeps = {
store: Pick<StoreApi<AppState>, 'getState' | 'setState'>
@@ -121,7 +121,7 @@ export function createDirectSshHostHydration(
const setTimer: NonNullable<DirectSshHostHydrationDeps['setTimer']> =
deps.setTimer ?? ((callback, delayMs) => setTimeout(callback, delayMs))
const clearTimer: NonNullable<DirectSshHostHydrationDeps['clearTimer']> =
deps.clearTimer ?? ((timer) => clearTimeout(timer as ReturnType<typeof setTimeout>))
deps.clearTimer ?? ((timer) => clearTimeout(timer))
const catalogRevisionByTarget = new Map<string, number>()
const catalogInFlight = new Map<string, Promise<'complete' | 'degraded' | 'stale'>>()
const pendingDeadlines = new Set<{ timer: HostReadTimer; settle: () => void }>()
@@ -5,7 +5,7 @@ export type DirectSshReconnectTargetState = {
authority: DirectSshAuthority
installedAt: number
dampUntil: number | null
timer: DirectSshReconnectTimer
timer: DirectSshReconnectTimer | null
}
export function createDirectSshReconnectTargetState(
@@ -113,7 +113,7 @@ export type DirectSshCoordinatorTelemetry = {
damped: boolean
}
export type DirectSshReconnectTimer = unknown
export type DirectSshReconnectTimer = ReturnType<typeof setTimeout>
export type DirectSshReconnectCoordinatorDeps = {
scheduler: DirectSshWorktreeRefreshScheduler
@@ -42,9 +42,7 @@ export function createDirectSshReconnectCoordinator(
const now = deps.now ?? Date.now
const setTimer =
deps.setTimer ?? ((callback: () => void, delayMs: number) => setTimeout(callback, delayMs))
const clearTimer =
deps.clearTimer ??
((timer: DirectSshReconnectTimer) => clearTimeout(timer as ReturnType<typeof setTimeout>))
const clearTimer = deps.clearTimer ?? ((timer: DirectSshReconnectTimer) => clearTimeout(timer))
const stabilizationMs = deps.stabilizationMs ?? DIRECT_SSH_RELAY_STABILIZATION_MS
const targets = new Map<string, DirectSshReconnectTargetState>()
let stopped = false