diff --git a/src/google-maps/map-event-manager.ts b/src/google-maps/map-event-manager.ts index 0a85bc8fb39f..54120e7da97a 100644 --- a/src/google-maps/map-event-manager.ts +++ b/src/google-maps/map-event-manager.ts @@ -12,17 +12,17 @@ import {switchMap} from 'rxjs/operators'; type MapEventManagerTarget = | { - addListener: ( + addListener( name: string, - callback: (...args: any[]) => void, - ) => google.maps.MapsEventListener | undefined; + callback: (...args: T) => void, + ): google.maps.MapsEventListener | undefined; } | undefined; /** Manages event on a Google Maps object, ensuring that events are added only when necessary. */ export class MapEventManager { /** Pending listeners that were added before the target was set. */ - private _pending: {observable: Observable; observer: Subscriber}[] = []; + private _pending: {observable: Observable; observer: Subscriber}[] = []; private _listeners: google.maps.MapsEventListener[] = []; private _targetStream = new BehaviorSubject(undefined); diff --git a/src/material-date-fns-adapter/adapter/date-fns-adapter.ts b/src/material-date-fns-adapter/adapter/date-fns-adapter.ts index 29e3b9927c83..91e37fb1cc2d 100644 --- a/src/material-date-fns-adapter/adapter/date-fns-adapter.ts +++ b/src/material-date-fns-adapter/adapter/date-fns-adapter.ts @@ -161,7 +161,7 @@ export class DateFnsAdapter extends DateAdapter { return new Date(); } - parse(value: any, parseFormat: string | string[]): Date | null { + parse(value: unknown, parseFormat: string | string[]): Date | null { if (typeof value == 'string' && value.length > 0) { const iso8601Date = parseISO(value); @@ -222,7 +222,7 @@ export class DateFnsAdapter extends DateAdapter { * (https://www.ietf.org/rfc/rfc3339.txt) into valid Dates and empty string into null. Returns an * invalid date for all other values. */ - override deserialize(value: any): Date | null { + override deserialize(value: unknown): Date | null { if (typeof value === 'string') { if (!value) { return null; @@ -235,7 +235,7 @@ export class DateFnsAdapter extends DateAdapter { return super.deserialize(value); } - isDateInstance(obj: any): boolean { + isDateInstance(obj: unknown): obj is Date { return isDate(obj); } @@ -277,7 +277,7 @@ export class DateFnsAdapter extends DateAdapter { return getSeconds(date); } - override parseTime(value: any, parseFormat: string | string[]): Date | null { + override parseTime(value: unknown, parseFormat: string | string[]): Date | null { return this.parse(value, parseFormat); } diff --git a/src/material-experimental/column-resize/column-resize.spec.ts b/src/material-experimental/column-resize/column-resize.spec.ts index 045ad22c6d82..47ff9f13aa71 100644 --- a/src/material-experimental/column-resize/column-resize.spec.ts +++ b/src/material-experimental/column-resize/column-resize.spec.ts @@ -333,7 +333,7 @@ class ElementDataSource extends DataSource { } // There's 1px of variance between different browsers in terms of positioning. -const approximateMatcher = { +const approximateMatcher: jasmine.CustomMatcherFactories = { isApproximately: () => ({ compare: (actual: number, expected: number) => { const result = { @@ -348,6 +348,14 @@ const approximateMatcher = { }), }; +interface NumberMatchers extends jasmine.Matchers { + isApproximately(expected: number): void; + not: NumberMatchers; +} +declare global { + function expect(actual: number): NumberMatchers; +} + const testCases = [ [MatColumnResizeModule, MatResizeTest, 'opt-in table-based mat-table'], [MatColumnResizeModule, MatResizeOnPushTest, 'inside OnPush component'], @@ -409,12 +417,8 @@ describe('Material Popover Edit', () => { component.getOverlayThumbElement(2).classList.contains('mat-column-resize-overlay-thumb'), ).toBe(true); - (expect(component.getOverlayThumbElement(0).offsetHeight) as any).isApproximately( - headerRowHeight, - ); - (expect(component.getOverlayThumbElement(2).offsetHeight) as any).isApproximately( - headerRowHeight, - ); + expect(component.getOverlayThumbElement(0).offsetHeight).isApproximately(headerRowHeight); + expect(component.getOverlayThumbElement(2).offsetHeight).isApproximately(headerRowHeight); component.beginColumnResizeWithMouse(0); @@ -425,15 +429,11 @@ describe('Material Popover Edit', () => { component.getOverlayThumbElement(2).classList.contains('mat-column-resize-overlay-thumb'), ).toBe(true); - (expect(component.getOverlayThumbElement(0).offsetHeight) as any).isApproximately( - tableHeight, - ); - (expect(component.getOverlayThumbTopElement(0).offsetHeight) as any).isApproximately( - headerRowHeight, - ); - (expect(component.getOverlayThumbElement(2).offsetHeight) as any).isApproximately( + expect(component.getOverlayThumbElement(0).offsetHeight).isApproximately(tableHeight); + expect(component.getOverlayThumbTopElement(0).offsetHeight).isApproximately( headerRowHeight, ); + expect(component.getOverlayThumbElement(2).offsetHeight).isApproximately(headerRowHeight); component.completeResizeWithMouseInProgress(0); component.endHoverState(); @@ -462,15 +462,15 @@ describe('Material Popover Edit', () => { let columnPositionDelta = component.getColumnOriginPosition(1) - initialColumnPosition; // let nextColumnPositionDelta = // component.getColumnOriginPosition(2) - initialNextColumnPosition; - (expect(thumbPositionDelta) as any).isApproximately(columnPositionDelta); + expect(thumbPositionDelta).isApproximately(columnPositionDelta); // TODO: This was commented out after switching from the legacy table to the current // MDC-based table. This failed by being inaccurate by several pixels. - // (expect(nextColumnPositionDelta) as any).isApproximately(columnPositionDelta); + // expect(nextColumnPositionDelta).isApproximately(columnPositionDelta); // TODO: This was commented out after switching from the legacy table to the current // MDC-based table. This failed by being inaccurate by several pixels. - // (expect(component.getTableWidth()) as any).isApproximately(initialTableWidth + 5); - (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth + 5); + // expect(component.getTableWidth()).isApproximately(initialTableWidth + 5); + expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 5); component.updateResizeWithMouseInProgress(1); fixture.detectChanges(); @@ -478,15 +478,15 @@ describe('Material Popover Edit', () => { thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; columnPositionDelta = component.getColumnOriginPosition(1) - initialColumnPosition; - (expect(thumbPositionDelta) as any).isApproximately(columnPositionDelta); + expect(thumbPositionDelta).isApproximately(columnPositionDelta); - (expect(component.getTableWidth()) as any).isApproximately(initialTableWidth + 1); - (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth + 1); + expect(component.getTableWidth()).isApproximately(initialTableWidth + 1); + expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 1); component.completeResizeWithMouseInProgress(1); flush(); - (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth + 1); + expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 1); component.endHoverState(); fixture.detectChanges(); @@ -508,8 +508,8 @@ describe('Material Popover Edit', () => { flush(); let thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; - (expect(thumbPositionDelta) as any).isApproximately(5); - (expect(component.getColumnWidth(1)) as any).toBe(initialColumnWidth); + expect(thumbPositionDelta).isApproximately(5); + expect(component.getColumnWidth(1)).toBe(initialColumnWidth); component.updateResizeWithMouseInProgress(1); fixture.detectChanges(); @@ -517,14 +517,14 @@ describe('Material Popover Edit', () => { thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; - (expect(component.getTableWidth()) as any).toBe(initialTableWidth); - (expect(component.getColumnWidth(1)) as any).toBe(initialColumnWidth); + expect(component.getTableWidth()).toBe(initialTableWidth); + expect(component.getColumnWidth(1)).toBe(initialColumnWidth); component.completeResizeWithMouseInProgress(1); flush(); - (expect(component.getTableWidth()) as any).isApproximately(initialTableWidth + 1); - (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth + 1); + expect(component.getTableWidth()).isApproximately(initialTableWidth + 1); + expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 1); component.endHoverState(); fixture.detectChanges(); @@ -562,18 +562,18 @@ describe('Material Popover Edit', () => { let thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; let columnPositionDelta = component.getColumnOriginPosition(1) - initialColumnPosition; - (expect(thumbPositionDelta) as any).isApproximately(columnPositionDelta); + expect(thumbPositionDelta).isApproximately(columnPositionDelta); - (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth + 5); + expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 5); // TODO: This was commented out after switching from the legacy table to the current // MDC-based table. This failed by being inaccurate by several pixels. - // (expect(component.getTableWidth()) as any).isApproximately(initialTableWidth + 5); + // expect(component.getTableWidth()).isApproximately(initialTableWidth + 5); dispatchKeyboardEvent(document, 'keyup', ESCAPE); flush(); - (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth); - (expect(component.getTableWidth()) as any).isApproximately(initialTableWidth); + expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth); + expect(component.getTableWidth()).isApproximately(initialTableWidth); component.endHoverState(); fixture.detectChanges(); @@ -582,7 +582,7 @@ describe('Material Popover Edit', () => { it('notifies subscribers of a completed resize via ColumnResizeNotifier', fakeAsync(() => { const initialColumnWidth = component.getColumnWidth(1); - let resize: ColumnSize | null = null; + let resize: ColumnSize | null = null as ColumnSize | null; component.columnResize.columnResizeNotifier.resizeCompleted.subscribe(size => { resize = size; }); @@ -596,7 +596,7 @@ describe('Material Popover Edit', () => { fixture.detectChanges(); flush(); - expect(resize).toEqual({columnId: 'name', size: initialColumnWidth + 5} as any); + expect(resize).toEqual({columnId: 'name', size: initialColumnWidth + 5}); component.endHoverState(); fixture.detectChanges(); @@ -626,12 +626,12 @@ describe('Material Popover Edit', () => { it('performs a column resize triggered via ColumnResizeNotifier', fakeAsync(() => { // Pre-verify that we are not updating the size to the initial size. - (expect(component.getColumnWidth(1)) as any).not.isApproximately(173); + expect(component.getColumnWidth(1)).not.isApproximately(173); component.columnResize.columnResizeNotifier.resize('name', 173); flush(); - (expect(component.getColumnWidth(1)) as any).isApproximately(173); + expect(component.getColumnWidth(1)).isApproximately(173); })); }); } @@ -660,13 +660,13 @@ describe('Material Popover Edit', () => { })); it('applies the persisted size', fakeAsync(() => { - (expect(component.getColumnWidth(1)).not as any).isApproximately(300); + expect(component.getColumnWidth(1)).not.isApproximately(300); columnSizeStore.emitSize('theTable', 'name', 300); flush(); - (expect(component.getColumnWidth(1)) as any).isApproximately(300); + expect(component.getColumnWidth(1)).isApproximately(300); })); it('persists the user-triggered size update', fakeAsync(() => { @@ -689,7 +689,7 @@ describe('Material Popover Edit', () => { const {tableId, columnId, sizePx} = columnSizeStore.setSizeCalls[0]; expect(tableId).toBe('theTable'); expect(columnId).toBe('name'); - (expect(sizePx) as any).isApproximately(initialColumnWidth + 5); + expect(sizePx).isApproximately(initialColumnWidth + 5); })); it('persists the user-triggered size update (live updates off)', fakeAsync(() => { @@ -714,7 +714,7 @@ describe('Material Popover Edit', () => { const {tableId, columnId, sizePx} = columnSizeStore.setSizeCalls[0]; expect(tableId).toBe('theTable'); expect(columnId).toBe('name'); - (expect(sizePx) as any).isApproximately(initialColumnWidth + 5); + expect(sizePx).isApproximately(initialColumnWidth + 5); })); }); }); diff --git a/src/material-luxon-adapter/adapter/luxon-date-adapter.ts b/src/material-luxon-adapter/adapter/luxon-date-adapter.ts index c465fd8d45a1..30d473b764b8 100644 --- a/src/material-luxon-adapter/adapter/luxon-date-adapter.ts +++ b/src/material-luxon-adapter/adapter/luxon-date-adapter.ts @@ -177,7 +177,7 @@ export class LuxonDateAdapter extends DateAdapter { return this._useUTC ? LuxonDateTime.utc(options) : LuxonDateTime.local(options); } - parse(value: any, parseFormat: string | string[]): LuxonDateTime | null { + parse(value: unknown, parseFormat: string | string[]): LuxonDateTime | null { const options: LuxonDateTimeOptions = this._getOptions(); if (typeof value == 'string' && value.length > 0) { @@ -245,7 +245,7 @@ export class LuxonDateAdapter extends DateAdapter { * (https://www.ietf.org/rfc/rfc3339.txt) and valid Date objects into valid DateTime and empty * string into null. Returns an invalid date for all other values. */ - override deserialize(value: any): LuxonDateTime | null { + override deserialize(value: unknown): LuxonDateTime | null { const options = this._getOptions(); let date: LuxonDateTime | undefined; if (value instanceof Date) { @@ -263,7 +263,7 @@ export class LuxonDateAdapter extends DateAdapter { return super.deserialize(value); } - isDateInstance(obj: any): boolean { + isDateInstance(obj: unknown): obj is LuxonDateTime { return obj instanceof LuxonDateTime; } @@ -315,7 +315,7 @@ export class LuxonDateAdapter extends DateAdapter { return date.second; } - override parseTime(value: any, parseFormat: string | string[]): LuxonDateTime | null { + override parseTime(value: unknown, parseFormat: string | string[]): LuxonDateTime | null { const result = this.parse(value, parseFormat); if ((!result || !this.isValid(result)) && typeof value === 'string') { diff --git a/src/material-moment-adapter/adapter/moment-date-adapter.ts b/src/material-moment-adapter/adapter/moment-date-adapter.ts index cbf303d33958..f1b4ac96aff5 100644 --- a/src/material-moment-adapter/adapter/moment-date-adapter.ts +++ b/src/material-moment-adapter/adapter/moment-date-adapter.ts @@ -187,7 +187,7 @@ export class MomentDateAdapter extends DateAdapter { return this._createMoment().locale(this.locale); } - parse(value: any, parseFormat: string | string[]): Moment | null { + parse(value: unknown, parseFormat: string | string[]): Moment | null { if (value && typeof value == 'string') { return this._createMoment(value, parseFormat, this.locale); } @@ -223,7 +223,7 @@ export class MomentDateAdapter extends DateAdapter { * (https://www.ietf.org/rfc/rfc3339.txt) and valid Date objects into valid Moments and empty * string into null. Returns an invalid date for all other values. */ - override deserialize(value: any): Moment | null { + override deserialize(value: unknown): Moment | null { let date; if (value instanceof Date) { date = this._createMoment(value).locale(this.locale); @@ -243,7 +243,7 @@ export class MomentDateAdapter extends DateAdapter { return super.deserialize(value); } - isDateInstance(obj: any): boolean { + isDateInstance(obj: unknown): obj is Moment { return moment.isMoment(obj); } @@ -285,7 +285,7 @@ export class MomentDateAdapter extends DateAdapter { return date.seconds(); } - override parseTime(value: any, parseFormat: string | string[]): Moment | null { + override parseTime(value: unknown, parseFormat: string | string[]): Moment | null { return this.parse(value, parseFormat); } diff --git a/src/universal-app/hydration.e2e.spec.ts b/src/universal-app/hydration.e2e.spec.ts index 974b1fcd289d..ace95ae861dc 100644 --- a/src/universal-app/hydration.e2e.spec.ts +++ b/src/universal-app/hydration.e2e.spec.ts @@ -1,5 +1,14 @@ import {browser, by, element, ExpectedConditions} from 'protractor'; +declare global { + interface Window { + ngDevMode: { + hydratedComponents: number; + componentsSkippedHydration: number; + }; + } +} + describe('hydration e2e', () => { beforeEach(async () => { await browser.waitForAngularEnabled(false); @@ -27,7 +36,7 @@ async function getHydrationState() { hydratedComponents: number; componentsSkippedHydration: number; }>(() => ({ - hydratedComponents: (window as any).ngDevMode.hydratedComponents, - componentsSkippedHydration: (window as any).ngDevMode.componentsSkippedHydration, + hydratedComponents: window.ngDevMode.hydratedComponents, + componentsSkippedHydration: window.ngDevMode.componentsSkippedHydration, })); } diff --git a/src/universal-app/kitchen-sink/kitchen-sink.ts b/src/universal-app/kitchen-sink/kitchen-sink.ts index 77f9865585ad..0c264c93ee13 100644 --- a/src/universal-app/kitchen-sink/kitchen-sink.ts +++ b/src/universal-app/kitchen-sink/kitchen-sink.ts @@ -62,8 +62,15 @@ import {MatTooltipModule} from '@angular/material/tooltip'; import {YouTubePlayer} from '@angular/youtube-player'; import {Observable, of as observableOf} from 'rxjs'; -export class TableDataSource extends DataSource { - connect(): Observable { +interface ElementItem { + position: number; + name: string; + weight: number; + symbol: string; +} + +export class TableDataSource extends DataSource { + connect(): Observable { return observableOf([ {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, diff --git a/src/youtube-player/fake-youtube-player.ts b/src/youtube-player/fake-youtube-player.ts index b48368359b2c..c71c329d13db 100644 --- a/src/youtube-player/fake-youtube-player.ts +++ b/src/youtube-player/fake-youtube-player.ts @@ -30,6 +30,11 @@ interface FakeYtNamespace { namespace: typeof YT; } +type ListenersStore = {[E in EventName]?: Set>}; +type Listener = NonNullable; +type ListenerArg = + Listener extends YT.PlayerEventHandler ? T : never; + export function createFakeYtNamespace(): FakeYtNamespace { const playerSpy: jasmine.SpyObj = jasmine.createSpyObj('Player', [ 'getPlayerState', @@ -63,7 +68,7 @@ export function createFakeYtNamespace(): FakeYtNamespace { ]); let playerConfig: YT.PlayerOptions | undefined; - const boundListeners = new Map void>>(); + const boundListeners: ListenersStore = {}; const playerCtorSpy = jasmine.createSpy('Player Constructor'); // The spy target function cannot be an arrow-function as this breaks when created through `new`. @@ -72,28 +77,27 @@ export function createFakeYtNamespace(): FakeYtNamespace { return playerSpy; }); - playerSpy.addEventListener.and.callFake((name: keyof YT.Events, listener: (e: any) => any) => { - if (!boundListeners.has(name)) { - boundListeners.set(name, new Set()); + playerSpy.addEventListener.and.callFake((name, listener) => { + const store: ListenersStore = boundListeners; + if (!store[name]) { + store[name] = new Set(); } - boundListeners.get(name)!.add(listener); + store[name].add(listener); }); - playerSpy.removeEventListener.and.callFake((name: keyof YT.Events, listener: (e: any) => any) => { - if (boundListeners.has(name)) { - boundListeners.get(name)!.delete(listener); - } + playerSpy.removeEventListener.and.callFake((name, listener) => { + boundListeners[name]?.delete(listener); }); - function eventHandlerFactory(name: keyof YT.Events) { - return (arg: Object = {}) => { + function eventHandlerFactory(name: EventName) { + return (arg = {} as ListenerArg) => { if (!playerConfig) { throw new Error(`Player not initialized before ${name} called`); } - if (boundListeners.has(name)) { - boundListeners.get(name)!.forEach(callback => callback(arg)); - } + boundListeners[name]?.forEach(callback => + (callback as (arg: ListenerArg) => void)(arg), + ); }; } diff --git a/src/youtube-player/youtube-player.spec.ts b/src/youtube-player/youtube-player.spec.ts index 757baf8bf435..b0cfafebdb2a 100644 --- a/src/youtube-player/youtube-player.spec.ts +++ b/src/youtube-player/youtube-player.spec.ts @@ -10,8 +10,10 @@ import { } from './youtube-player'; import {PlaceholderImageQuality} from './youtube-player-placeholder'; +declare var window: Window; + const VIDEO_ID = 'a12345'; -const YT_LOADING_STATE_MOCK = {loading: 1, loaded: 0}; +const YT_LOADING_STATE_MOCK = {loading: 1, loaded: 0} as unknown as typeof YT; const TEST_PROVIDERS: (Provider | EnvironmentProviders)[] = [ { provide: YOUTUBE_PLAYER_CONFIG, @@ -56,7 +58,7 @@ describe('YoutubePlayer', () => { }); afterEach(() => { - (window as any).YT = undefined; + window.YT = undefined; window.onYouTubeIframeAPIReady = undefined; }); @@ -540,17 +542,17 @@ describe('YoutubePlayer', () => { let api: typeof YT; beforeEach(() => { - api = window.YT; - (window as any).YT = undefined; + api = window.YT!; + window.YT = undefined; }); afterEach(() => { - (window as any).YT = undefined; + window.YT = undefined; window.onYouTubeIframeAPIReady = undefined; }); it('waits until the api is ready before initializing', () => { - (window.YT as any) = YT_LOADING_STATE_MOCK; + window.YT = YT_LOADING_STATE_MOCK; TestBed.configureTestingModule({providers: TEST_PROVIDERS}); fixture = TestBed.createComponent(TestApp); testComponent = fixture.debugElement.componentInstance; @@ -560,7 +562,7 @@ describe('YoutubePlayer', () => { expect(playerCtorSpy).not.toHaveBeenCalled(); - window.YT = api!; + window.YT = api; window.onYouTubeIframeAPIReady!(); expect(playerCtorSpy).toHaveBeenCalledWith( @@ -585,7 +587,7 @@ describe('YoutubePlayer', () => { expect(playerCtorSpy).not.toHaveBeenCalled(); - window.YT = api!; + window.YT = api; window.onYouTubeIframeAPIReady!(); expect(spy).toHaveBeenCalled(); @@ -601,7 +603,7 @@ describe('YoutubePlayer', () => { }); afterEach(() => { - fixture = testComponent = (window as any).YT = window.onYouTubeIframeAPIReady = undefined!; + fixture = testComponent = window.YT = window.onYouTubeIframeAPIReady = undefined!; }); it('should show a placeholder', () => {