refactor(types): consolidate duplicated types across src/ into single sources of truth#717
Merged
Conversation
Replace inline duplicates of SessionSurface, ClickButton, DeviceRotation, BackMode, ScrollDirection, Platform/PlatformSelector/DeviceTarget, AlertAction, and LeaseBackend with imports of the existing canonical types. Extract BackMode into a core/back-mode.ts leaf (matching click-button.ts / session-surface.ts) to keep backend.ts dependency-clean. Add 'satisfies readonly T[]' drift-guards to the runtime enum tuples consumed by enumField. Pure refactor: single source of truth for these unions, no behavior change.
- Add SwipePattern to core/scroll-gesture.ts; reuse SwipePreset, ScrollInputDirection, ScrollDirection at remaining inline sites. - Move DaemonServerMode / DaemonTransportPreference / SessionIsolationMode / NetworkIncludeMode to contracts.ts (the client<->daemon boundary); daemon/ config.ts and daemon/network-log.ts re-export them. Drop client-types.ts's three private alias copies. - Reuse MetroPrepareKind in metro.ts and remote-config-schema.ts. - Add satisfies-guards to the runtime enum tuples. Pure refactor, type-only changes.
- ElementSelectorKey (core/interactor-types.ts) for the 'id|label|text|value' selector-key subset across core/daemon/ios/maestro. - GESTURE_KINDS + GestureKind (command-catalog.ts), dropping the duplicate GESTURE_KIND_VALUES. - AndroidTextInputAction (android/adb-executor.ts); reuse NetworkLogBackend for the app-log backend union. - Reuse contracts.ts JsonRpcId / JsonRpcRequestEnvelope in mcp router + server. - New commands/log-command-contract.ts (LOG_ACTION_VALUES + LogAction), mirroring perf-command-contract.ts. - Named Android snapshot helper metadata unions (transport/captureMode/install reason) shared between helper + backend metadata. Pure refactor, type-only changes; full unit suite green.
- Reuse canonical Rect (utils/snapshot.ts) for inline {x,y,width,height}
literals (parsing, output, screenshot-diff regions/ocr, atspi-bridge).
- GestureReferenceFrame (core/scroll-gesture.ts) as the single reference-frame
type; TouchReferenceFrame becomes an alias; replace inline
{referenceWidth,referenceHeight} across daemon + maestro + commands.
- New ImageDimensions (screenshot-geometry.ts) and MovementRange
(screenshot-diff-ocr.ts) for repeated {width,height} / {min,max} shapes.
- File-local AndroidRecordingSize in record-trace-android.ts.
Pure refactor, type-only changes. Point literals with normalized-vs-absolute
semantics deliberately left untouched.
- Generic PlatformProviderResolver<T> collapses 6 near-identical resolver types in request-platform-providers.ts. - Reuse canonical DaemonError (contracts.ts) / NormalizedError (utils/errors.ts) for the inline error DTOs in daemon/types.ts and utils/output.ts. - Single DaemonFailureResponse: FailedDaemonResponse becomes an alias and the maestro-local redefinition is dropped. - Extract one shared toBackendResult() into commands/runtime-types.ts, deleting 5 duplicate copies. - Normalize whitespace with oxfmt across the touched files. Full unit suite green.
- TransformGestureParams (core/scroll-gesture.ts) replaces 4 identical inline transform-gesture param shapes (core interactor, dispatch, android multitouch, client options). - Reuse RepeatedInput (commands/command-input.ts) for the tap-modifier bundle in PressCommandOptions and BackendTapOptions. Pure refactor, type-only.
Replace the repeated inline { backendResult?: Record<string, unknown>;
message?: string } pair on ~17 single-object command result types with
'& BackendResultEnvelope' (commands/runtime-types.ts). Discriminated-union
variants and single-field result types are intentionally left inline.
Pure refactor, type-only changes; failing files re-verified green in isolation
(full-suite failures were flaky timeouts).
- RunnerSessionOptions = AppleRunnerLifecycleOptions (field-identical).
- Reuse ReplayActionBlockInvoker for the maestro + daemon replay invoker types.
- SelectorSnapshotOptions aliases the canonical SelectorSnapshotInput; annotate
selectorSnapshotOptionsFromFlags.
- Reuse ExecResult for the { stdout; stderr; exitCode } subset in
record-trace-errors and app-log-process.
Pure refactor, type-only.
Size Report
Startup median (7 runs, lower is better):
Top changed chunks:
|
Each string-enum module now exports an 'as const' literal tuple as the single source and derives its union via (typeof TUPLE)[number]: SESSION_SURFACES, CLICK_BUTTONS, DEVICE_ROTATIONS, BACK_MODES, SCROLL_DIRECTIONS/SWIPE_PRESETS/ SWIPE_PATTERNS, SCROLL_INPUT_DIRECTIONS, ALERT_ACTIONS, DEVICE_TARGETS. The command metadata/input files import these tuples instead of redefining local *_VALUES copies, which also retires 10 now-redundant 'satisfies' drift-guards. Member order preserved everywhere (enumField error messages unchanged). Platform tuples intentionally left as-is (command-input vs contracts use different orders). Net -39 lines; tuple+type dual maintenance eliminated for these unions.
|
This was referenced Jun 9, 2026
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
A pure type-consolidation refactor: replaces duplicated TypeScript types across
src/with shared canonical types / aliases / type-only imports. Goal is single source of truth + type safety with no behavior change. All new imports are type-only (erase at runtime underverbatimModuleSyntax).Found via a discovery sweep of
src/(69 verified consolidation opportunities); ~48 were implemented here. Every change was checked withtsc, and the whole diff was run through an adversarial semantic review — verdict: clean, zero regressions.core/back-mode.ts,commands/log-command-contract.ts)tsc✓,oxlint✓importline); the win is ~48 type concepts now single-sourced instead of duplicated.What changed (by theme)
String-literal unions → one definition, reused everywhere
SessionSurface,ClickButton,DeviceRotation,BackMode,ScrollDirection/ScrollInputDirection/SwipePreset/SwipePattern,Platform/PlatformSelector/DeviceTarget,AlertAction,LeaseBackend,DaemonServerMode/DaemonTransportPreference/SessionIsolationMode/NetworkIncludeMode(promoted tocontracts.ts, the client↔daemon boundary, so the daemon and client/CLI stop redefining them),MetroPrepareKind,ElementSelectorKey,GestureKind,AndroidTextInputAction,NetworkLogBackend,JsonRpcId/JsonRpcRequestEnvelope,LogAction, Android snapshot-helper metadata unions. Runtime enum tuples gainedas const satisfies readonly T[]drift-guards (behavior-neutral).Geometry
Reuse canonical
Rect; oneGestureReferenceFrame(TouchReferenceFrameis now an alias); newImageDimensions/MovementRange. Normalized-vs-absolute point literals were deliberately left untouched (different meaning).Result / options / function shapes (the LOC-reducing part)
BackendResultEnvelopemix-in (~17 result types), one sharedtoBackendResult(was 5 copies), genericPlatformProviderResolver<T>(was 6 near-identical types),TransformGestureParams,RepeatedInput,DaemonError/NormalizedErrorreuse,DaemonFailureResponse,ReplayActionBlockInvoker,RunnerSessionOptions = AppleRunnerLifecycleOptions,SelectorSnapshotInput,ExecResult.Notes for the reviewer
toBackendResult(identical logic, param widenedBackendActionResult→unknown, which is safe for all callers) and reusing the existingGESTURE_KINDStuple in place of an identical local copy.NetworkLogBackendis reused for the app-log backend union (same members) despite the name — candidate for a future rename.daemon-invoke-fn,internal-result-failure-response,shutdown-command-result,envmap-record) were intentionally deferred; happy to do them in a follow-up if wanted.Test plan
pnpm typecheckpnpm lintpnpm test:unit(green in uncontended runs; a few process-spawning android/ios tests time out flakily under load but pass in isolation — pre-existing, unrelated to these type-only changes)