Skip to content

Replace unsafe/legacy types in ui-kit utilities, directives, layout, and misc small areas - #702

Open
fpigeonjr wants to merge 6 commits into
gh-582-apply-safe-eslint-autofixes-and-lower-the-baselinefrom
gh-586-replace-unsafe-and-legacy-typescript-types
Open

Replace unsafe/legacy types in ui-kit utilities, directives, layout, and misc small areas#702
fpigeonjr wants to merge 6 commits into
gh-582-apply-safe-eslint-autofixes-and-lower-the-baselinefrom
gh-586-replace-unsafe-and-legacy-typescript-types

Conversation

@fpigeonjr

Copy link
Copy Markdown
Contributor

Description

Replaces unsafe/legacy TypeScript types (@typescript-eslint/no-explicit-any, no-unsafe-function-type) across four small, coherent areas of the codebase, as a first slice of #586:

  • ui-kit/utilitiesare-equal.ts, deprecator.ts, key-helper.ts. Added a KeyEventLike interface and toKeyEventLike() guard so KeyHelper no longer needs any for malformed/partial event input while staying tolerant of it.
  • ui-kit/directivestaboutside.directive.ts, sticky.component.ts. Added an exported OffsetParentLike interface so sticky.component.ts's getElemDistanceToTop can be typed without assuming a real DOM HTMLElement (specs pass plain mock objects).
  • ui-kit/layout — filter-drawer (dynamic-chips.directive.ts + chip/item/drawer components), filters-wrapper.component.ts, pagination.component.ts, toolbar.component.ts. Added FilterField/FilterDrawerChipModel interfaces; typed emitters as unknown/Record<string, unknown>/ToolbarItem instead of any; gave pagination's options input a concrete inline shape matching its template usage.
  • Misc small areasformly/sam-formly.ts (made AbstractSamFormly generic over a new SamFormlyTemplateComponent constraint instead of using any for the wrapped template component), type-check-helpers.ts (isString/isObject/isArray/safeTypeOf now take unknown), types.ts (HistoryNodeType.queryParams, AutocompleteConfig.serviceOptions, new UploadedFileIcon interface for UploadedFileData.icon), typings.d.ts (*.json module value → unknown), elements/button (onClickEventEmitter<Event>, btnClassMapRecord<string, string>), wrappers/fieldset-wrapper (errorMessagesstring[], hintContainerElementRef<HTMLElement>, handler parameters typed), filters.component.ts (modelRecord<string, unknown>), pipes/date-time-display.pipe.ts (transform typed as string | number | Date), formly/components/autocomplete/test.service.ts (fetch()Observable<unknown>).
  • Public API and consumer-compiled source compatibility preserved throughout — no breaking signature changes, only widening any/Function to precise or intentionally-generic (unknown, Record<string, unknown>) types.
  • Each slice's findings were inventoried by component area before implementation, verified via tsc --noEmit diffing (before/after via git stash) to confirm no new type errors, eslint on changed files to confirm target rules are resolved without new warnings, and the full test-app suite (152 files / 1386 tests) to confirm no regressions.
  • The ESLint root warning baseline has been lowered after each area: 1307 → 1289 → 1274 → 1259 → 1231 (this branch was rebased onto Apply safe ESLint autofixes and lower the warning baseline #675's no-wrapper-object-types autofixes first, which is why the starting point differs from Replace unsafe and legacy TypeScript types #586's pre-rebase snapshot).

This is the first of several planned PRs for #586 — the remaining, larger areas (layout-deprecated, form-templates, components, experimental, form-controls) are tracked as separate sub-issues linked to #586.

Motivation and Context

Progresses #586. Does not close it — several larger areas remain and will be filed as separate sub-issues/PRs.

Type of Change (Select One and Apply Label)

  • Bug fix (non-breaking change which fixes an issue) → Apply bugfix label
  • New feature (non-breaking change which adds functionality) → Apply enhancement label
  • Breaking change (fix or feature that would cause existing functionality to change) → Apply breaking label
  • Documentation / configuration update → Apply maintenance label

How to Test

  1. npm ci && npm ci --prefix test-app
  2. npm run lint — confirm 0 errors, warnings at/under the new baseline in eslint-baseline.json
  3. npx tsc -p tsconfig.json --noEmit — confirm no new compile errors
  4. npm --prefix test-app test — confirm all 152 spec files / 1386 tests pass
  5. npm run format:check — confirm clean

Expected result: All checks pass; ESLint root baseline is 1231 (down from 1259 pre-PR / 1307 pre-rebase); no any/Function usages remain in ui-kit/utilities, ui-kit/directives, ui-kit/layout, or the misc files listed above.

Screenshots (if appropriate)

N/A — type-only changes, no UI/visual impact.

Checklist

  • Branch name follows convention (e.g. gh-<number>-<slug>)
  • PR title starts with a verb in the imperative mood
  • I have self-reviewed my own code
  • format:check passes (npm run format:check)
  • lint passes (npm run lint)
  • build passes (cd test-app && npm run build)
  • Tests pass and coverage is reported (cd test-app && npm test)
  • If this change requires a documentation update, I have updated it accordingly
  • If there are dependent changes, they have been merged and published in downstream modules

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Public typing regressions, strict-null incompatibility, and stacked out-of-scope changes must be resolved before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Replaces unsafe TypeScript types across the Angular library, while also incorporating stacked lint autofixes and datepicker behavior fixes.

Changes:

  • Adds stronger public API, event, model, and lifecycle typings.
  • Fixes datepicker outside-click behavior with unit and browser tests.
  • Modernizes lint/RxJS patterns and lowers the warning baseline.
File summaries
File Description
test-app/src/typings.d.ts Modernizes ambient declaration
test-app/src/app/datepicker-gallery/datepicker-gallery.component.ts Adds datepicker gallery
test-app/src/app/datepicker-gallery/datepicker-gallery.component.spec.ts Tests gallery creation
test-app/src/app/datepicker-gallery/datepicker-gallery.component.html Adds datepicker harness
test-app/src/app/app.module.ts Registers gallery route
test-app/e2e/datepicker.spec.ts Adds browser regression tests
src/ui-kit/wrappers/label-wrapper/label-wrapper.spec.ts Types test fixture
src/ui-kit/wrappers/label-wrapper/label-wrapper.component.ts Declares lifecycle interfaces
src/ui-kit/wrappers/fieldset-wrapper/fieldset-wrapper.spec.ts Types fixture and changes
src/ui-kit/wrappers/fieldset-wrapper/fieldset-wrapper.component.ts Strengthens wrapper types
src/ui-kit/utilities/key-helper/key-helper.ts Adds typed event abstraction
src/ui-kit/utilities/key-helper/key-helper.spec.ts Applies const cleanup
src/ui-kit/utilities/deprecator/deprecator.ts Replaces unsafe object types
src/ui-kit/utilities/are-equal/are-equal.ts Accepts unknown values safely
src/ui-kit/typings.d.ts Types JSON as unknown
src/ui-kit/types.ts Strengthens shared models
src/ui-kit/type-check-helpers.ts Accepts unknown inputs
src/ui-kit/pipes/filesize/filesize.pipe.spec.ts Applies const cleanup
src/ui-kit/pipes/date-time-display/date-time-display.pipe.ts Types pipe contract
src/ui-kit/layout/toolbar/toolbar.spec.ts Types test fixture
src/ui-kit/layout/toolbar/toolbar.component.ts Types action output
src/ui-kit/layout/toolbar/aside-toggle.spec.ts Types fixtures
src/ui-kit/layout/toolbar/aside-toggle.component.ts Declares lifecycle interfaces
src/ui-kit/layout/pagination/pagination.component.ts Types pagination options
src/ui-kit/layout/pagination/pagination.component.spec.ts Applies const cleanup
src/ui-kit/layout/header/header.component.ts Applies const cleanup
src/ui-kit/layout/header/header.component.spec.ts Applies const cleanup
src/ui-kit/layout/filters-wrapper/filters-wrapper.component.ts Types report subjects
src/ui-kit/layout/filter-drawer/filter-drawer.component.ts Types clear output
src/ui-kit/layout/filter-drawer/filter-drawer-item/filter-drawer-item.component.ts Types filter removal
src/ui-kit/layout/filter-drawer/filter-drawer-chip/filter-drawer-chip.component.ts Types chip output
src/ui-kit/layout/filter-drawer/dynamic-chips/dynamic-chips.directive.ts Adds filter model types
src/ui-kit/layout-deprecated/page.spec.ts Applies const cleanup
src/ui-kit/layout-deprecated/list-results-message.spec.ts Applies const cleanup
src/ui-kit/layout-deprecated/grid/row.spec.ts Applies const cleanup
src/ui-kit/layout-deprecated/grid/grid.spec.ts Applies const cleanup
src/ui-kit/layout-deprecated/grid/column.spec.ts Applies const cleanup
src/ui-kit/layout-deprecated/grid/column.directive.ts Applies const cleanup
src/ui-kit/form-templates/phone-entry/phone-entry.component.ts Declares lifecycle interface
src/ui-kit/form-templates/international-phone/sam-international-prefix/international-prefix.component.ts Declares initialization lifecycle
src/ui-kit/form-templates/international-phone/sam-extension/extension.component.ts Declares initialization lifecycle
src/ui-kit/form-service.ts Replaces wrapper object type
src/ui-kit/form-controls/upload-v2/upload-v2.component.ts Declares lifecycle interfaces
src/ui-kit/form-controls/toggle-switch/toggle-switch.component.ts Applies const cleanup
src/ui-kit/form-controls/textarea/textarea.component.ts Adds lifecycle typing
src/ui-kit/form-controls/select/select.component.ts Adds initialization lifecycle
src/ui-kit/form-controls/sam-sds-autocomplete/selected-result/selected-result.component.ts Replaces legacy object type
src/ui-kit/form-controls/sam-sds-autocomplete/selected-result/selected-result.component.spec.ts Applies const cleanup
src/ui-kit/form-controls/sam-sds-autocomplete/selected-result/models/sds-selected-item-model-helper.ts Applies const cleanup
src/ui-kit/form-controls/sam-sds-autocomplete/autocomplete/autocomplete.component.spec.ts Applies const cleanup
src/ui-kit/form-controls/sam-sds-autocomplete/autocomplete-search/autocomplete-search.component.ts Modernizes local declarations
src/ui-kit/form-controls/sam-sds-autocomplete/autocomplete-search/autocomplete-search.component.spec.ts Applies const cleanup
src/ui-kit/form-controls/sam-sds-autocomplete/autocomplete-search/autocomplete-seach-test-service.spec.ts Modernizes test service types
src/ui-kit/form-controls/radiobutton/radiobutton.component.ts Declares lifecycle interfaces
src/ui-kit/form-controls/number/number.component.ts Declares lifecycle interfaces
src/ui-kit/form-controls/date/date.component.ts Adds lifecycle and consts
src/ui-kit/form-controls/checkbox/checkbox.component.ts Declares initialization lifecycle
src/ui-kit/form-controls/autocomplete/autocomplete.component.ts Adds lifecycle and consts
src/ui-kit/form-controls/autocomplete-multiselect/autocomplete-multiselect.component.ts Adds lifecycle and consts
src/ui-kit/filters/filters.component.ts Types filter model
src/ui-kit/experimental/video-player/video-player.component.ts Declares lifecycle interfaces
src/ui-kit/experimental/title/title.component.ts Applies const cleanup
src/ui-kit/experimental/tabs/tab-nav-bar/tab-nav-bar.ts Declares lifecycle interface
src/ui-kit/experimental/tabs/tab-group.ts Adds lifecycle and const
src/ui-kit/experimental/tabs/tab-body.ts Removes redundant aliases
src/ui-kit/experimental/sideNavigationToolbar/sideNavigationToolbar/sideNavigationToolbar.component.ts Declares lifecycle interface
src/ui-kit/experimental/search/search.service.ts Applies const cleanup
src/ui-kit/experimental/search/search.component.ts Adds lifecycle and const
src/ui-kit/experimental/patterns/layout/components/title-section.component.ts Keeps host ID synchronized
src/ui-kit/experimental/patterns/layout/components/sidenav/sidenav.ts Modernizes RxJS usage
src/ui-kit/experimental/patterns/layout/components/sidenav/sidenav.spec.ts Tests dynamic sidenavs
src/ui-kit/experimental/patterns/layout/components/page/page.component.ts Declares lifecycle interfaces
src/ui-kit/experimental/patterns/layout/components/actionbar.component.ts Declares lifecycle interface
src/ui-kit/experimental/listbox/listbox.component.ts Fixes announced label
src/ui-kit/experimental/layout/layout.component.ts Declares initialization lifecycle
src/ui-kit/experimental/hierarchical/selected-result/selected-result.component.spec.ts Applies const cleanup
src/ui-kit/experimental/hierarchical/models/SamHierarchicalTreeHeaderConfiguration.ts Replaces wrapper string
src/ui-kit/experimental/hierarchical/models/SamHierarchicalTreeConfiguration.ts Replaces wrapper string
src/ui-kit/experimental/hierarchical/models/SamHierarchicalConfiguration.ts Replaces wrapper string
src/ui-kit/experimental/hierarchical/hierarchical-tree/hierarchical-tree.component.ts Replaces legacy object types
src/ui-kit/experimental/hierarchical/hierarchical-tree/hierarchical-tree.component.spec.ts Applies const cleanup
src/ui-kit/experimental/hierarchical/hierarchical-tree-selectedItem.model.ts Applies const cleanup
src/ui-kit/experimental/hierarchical/hierarchical-tree-header/hierarchical-tree-header.component.spec.ts Applies const cleanup
src/ui-kit/experimental/hierarchical/hierarchical-tree-grid/hierarchical-tree-grid.component.ts Adds lifecycle and consts
src/ui-kit/experimental/hierarchical/hierarchical-tree-grid/hierarchical-tree-grid.component.spec.ts Applies const cleanup
src/ui-kit/experimental/hierarchical/hierarchical-test-service.spec.ts Modernizes test service types
src/ui-kit/experimental/hierarchical/autocomplete/autocomplete.component.ts Replaces legacy declarations
src/ui-kit/experimental/dollar/dollar.component.ts Declares lifecycle interfaces
src/ui-kit/experimental/date-range-v2/datepicker/picker.spec.ts Enables click regression tests
src/ui-kit/experimental/date-range-v2/datepicker/picker.component.ts Fixes popup click handling
src/ui-kit/experimental/date-range-v2/datepicker/calendar.spec.ts Applies const cleanup
src/ui-kit/experimental/button-next/button.component.ts Replaces wrapper string
src/ui-kit/experimental/aria/utils/events.ts Replaces wrapper object
src/ui-kit/experimental/aria/abstract-grid/abstract-grid.ts Replaces wrapper object
src/ui-kit/experimental/aria/abstract-grid/abstract-cell.ts Replaces wrapper object
src/ui-kit/experimental/aria/abstract-combobox/abstract-combobox.ts Replaces wrapper object
src/ui-kit/experimental/alert/alert.component.ts Declares initialization lifecycle
src/ui-kit/experimental/actions-list/actions-list.component.ts Adds lifecycle and consts
src/ui-kit/elements/button/button.spec.ts Types fixture and events
src/ui-kit/elements/button/button.component.ts Types button API
src/ui-kit/directives/tab-outside/taboutside.spec.ts Types fixture and output
src/ui-kit/directives/tab-outside/taboutside.directive.ts Types focus output
src/ui-kit/directives/sticky/sticky.spec.ts Types fixture and mocks
src/ui-kit/directives/sticky/sticky.component.ts Adds DOM-specific types
src/ui-kit/directives/focus/focus.spec.ts Types fixture and output
src/ui-kit/directives/external-link/external-link.spec.ts Applies const cleanup
src/ui-kit/directives/drag-drop/drag-drop.spec.ts Types test fixture
src/ui-kit/directives/click-outside/click-outside.spec.ts Types fixture and output
src/ui-kit/components/tabs/tabs.component.ts Declares changes lifecycle
src/ui-kit/components/sidenav/sidenav/sidenav.component.ts Declares changes lifecycle
src/ui-kit/components/sidenav/menu-item/menu-item.spec.ts Applies const cleanup
src/ui-kit/components/pagination/pagination.spec.ts Applies const cleanup
src/ui-kit/components/pagination/pagination.component.ts Replaces var declarations
src/ui-kit/components/page-title/page-title.component.ts Removes redundant alias
src/ui-kit/components/modal/modal.component.ts Adds lifecycle and consts
src/ui-kit/components/data-table/sort-header.component.ts Removes redundant alias
src/ui-kit/components/data-table/data-table.component.ts Declares changes lifecycle
src/ui-kit/components/comments/comments.spec.ts Applies const cleanup
src/ui-kit/components/comments/comments.component.ts Declares destruction lifecycle
src/ui-kit/components/alert/alert.component.ts Declares initialization lifecycle
src/ui-kit/components/alert-footer/alert-footer.component.ts Declares initialization lifecycle
src/ui-kit/components/actions/actions-dropdown/actions-dropdown.spec.ts Applies const cleanup
src/formly/sam-formly.ts Adds generic template contract
src/formly/components/autocomplete/test.service.ts Types observable result
eslint.config.mjs Adds RxJS misuse guard
eslint-baseline.json Lowers warning ceilings
Review details
  • Files reviewed: 124/126 changed files
  • Comments generated: 7
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread eslint-baseline.json
Comment thread src/ui-kit/experimental/date-range-v2/datepicker/picker.component.ts Outdated
Comment thread src/ui-kit/layout/pagination/pagination.component.ts Outdated
Comment thread src/ui-kit/pipes/date-time-display/date-time-display.pipe.ts Outdated
Comment thread src/ui-kit/types.ts Outdated
Comment thread src/ui-kit/experimental/listbox/listbox.component.ts
@fpigeonjr
fpigeonjr changed the base branch from master to gh-582-apply-safe-eslint-autofixes-and-lower-the-baseline September 3, 2026 18:29
@fpigeonjr
fpigeonjr force-pushed the gh-586-replace-unsafe-and-legacy-typescript-types branch from c669a84 to bb6a7ff Compare September 3, 2026 18:33
- are-equal.ts: any -> unknown, precise internal helper types
- deprecator.ts: any -> object for parentClass/render, typed record cast
  for dynamic property access
- key-helper.ts: introduce KeyEventLike to model the cross-browser event
  shapes this helper reads (including legacy keyIdentifier/numeric key
  fixtures), replacing all any/Function usages; preserves the original
  tolerant behavior for malformed event input via toKeyEventLike

Lowers the root ESLint warning baseline 1307 -> 1289.
- taboutside.directive.ts: EventEmitter<any> -> EventEmitter<void>,
  typed hasFocusChanged(target: EventTarget)
- sticky.component.ts: typed resize/scroll(event: Event), replaced any
  casts on getElementsByClassName results with
  HTMLCollectionOf<HTMLElement>, introduced exported OffsetParentLike
  interface for getElemDistanceToTop's recursive offsetParent walk
- click-outside/focus/tab-outside/drag-drop/sticky specs: replaced
  EventEmitter<any>/fixture: any with concrete
  EventEmitter<boolean>/ComponentFixture<TestComponent> types, and
  Event() instances instead of {}/undefined for resize/scroll calls

Lowers the root ESLint warning baseline 1289 -> 1274.
- dynamic-chips.directive.ts: typed `map` input, `remove` emitter, and
  internal filter/field mapping helpers (FilterField,
  FilterDrawerChipModel interfaces) instead of any/untyped params
- filter-drawer-chip.component.ts / filter-drawer-item.component.ts /
  filter-drawer.component.ts: EventEmitter<any> -> EventEmitter<unknown
  | Record<string, unknown> | void>, `values: any[]` -> `unknown[]`
- filters-wrapper.component.ts: Subject<any> -> Subject<unknown> for
  runReportEvent/resetReportEvent
- pagination.component.ts: `options: any[]` -> concrete option shape
  matching the template's usage (value/label/disabled/selected)
- toolbar.component.ts: EventEmitter<any> -> EventEmitter<ToolbarItem>
  matching the emitted contentModel item type
- aside-toggle.spec.ts / toolbar.spec.ts: `fixture: any` ->
  ComponentFixture<...>

Lowers the root ESLint warning baseline 1274 -> 1259.
Covers the remaining small pockets of unsafe/legacy types outside the
larger per-area slices already addressed: formly/sam-formly.ts,
type-check-helpers.ts, wrappers, elements, types.ts, pipes,
formly/components, filters, typings.d.ts.

- sam-formly.ts: AbstractSamFormly is now generic over a
  SamFormlyTemplateComponent-constrained template type instead of
  `any`; setProperties/ngOnInit typed against that generic and
  Record<string, unknown> configuration
- type-check-helpers.ts: isString/isObject/isArray/safeTypeOf take
  `unknown` instead of `any`
- types.ts: HistoryNodeType.queryParams -> Record<string, string |
  number | boolean>, AutocompleteConfig.serviceOptions -> unknown,
  UploadedFileData.icon -> new UploadedFileIcon interface (matches
  upload-v2 template's `icon.name`/`icon.iconClass` usage)
- typings.d.ts: `*.json` module value -> unknown
- elements/button: onClick -> EventEmitter<Event>, click($event) ->
  click($event: Event), btnClassMap -> Record<string, string>; spec
  updated to pass real Event instances and typed fixture
- wrappers/fieldset-wrapper: errorMessages -> string[], hintContainer
  -> ElementRef<HTMLElement>, ngOnChanges/onResize/toggleHint/
  calculateNumberOfLines/setInvalidError given concrete parameter
  types; specs updated with typed fixture and a complete SimpleChange
  mock
- wrappers/label-wrapper.spec.ts: typed fixture
- filters/filters.component.ts: model -> Record<string, unknown>
- pipes/date-time-display: transform(datetime) typed as
  string | number | Date, returns string | undefined
- formly/components/autocomplete/test.service.ts: fetch() ->
  Observable<unknown>

Lowers the root ESLint warning baseline 1259 -> 1231.
@fpigeonjr
fpigeonjr force-pushed the gh-586-replace-unsafe-and-legacy-typescript-types branch from bb6a7ff to 19d4137 Compare September 3, 2026 18:37
- Rebase branch tip onto latest #675 (gh-582) so this PR's diff/baseline
  reflect only #586's type-safety changes, not #675's still-open autofix
  set. #675 is CLEAN/MERGEABLE and independently reviewed; stacking is the
  documented convention for this repo's slice-based PRs.
- Retarget PR base to gh-582-apply-safe-eslint-autofixes-and-lower-the-baseline
  so the GitHub diff matches (rebase alone doesn't move a PR's base).
- Drop the #674 datepicker outside-click fix and #677 sidenav RxJS fix
  commits from this branch entirely (dropped during rebase) -- both are
  unrelated bugfixes already merged to master via their own PRs; they were
  only present here as inherited ancestry from an earlier base choice, not
  something this PR should carry or take credit for.
- pagination.component.ts: options.value widened to 'string | number' --
  the template already supports numeric option values via attribute
  binding; the prior 'any[]' allowed this and the fix's 'string' literal
  would have narrowed a supported case.
- date-time-display.pipe.ts: transform() parameter widened to include
  'undefined' explicitly -- the implementation's own guard branch handles
  undefined and the pipe previously accepted it; the stricter signature
  would have been a source-compatibility break for existing callers.
- types.ts: HistoryNodeType.queryParams value type widened to include
  readonly arrays and null, matching Angular Router's actual accepted
  queryParams value shapes (repeated params, param removal) instead of
  the narrower 'string | number | boolean' which would reject valid
  existing usage.
@fpigeonjr
fpigeonjr marked this pull request as ready for review September 3, 2026 19:42
@fpigeonjr
fpigeonjr requested a review from a team as a code owner September 3, 2026 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenance Repo maintenance / tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants