diff --git a/goldens/material/snack-bar/index.api.md b/goldens/material/snack-bar/index.api.md index 47dd8b7bcac1..493828be384e 100644 --- a/goldens/material/snack-bar/index.api.md +++ b/goldens/material/snack-bar/index.api.md @@ -32,10 +32,10 @@ import { TemplateRef } from '@angular/core'; import { ViewContainerRef } from '@angular/core'; // @public -export const MAT_SNACK_BAR_DATA: InjectionToken; +export const MAT_SNACK_BAR_DATA: InjectionToken; // @public -export const MAT_SNACK_BAR_DEFAULT_OPTIONS: InjectionToken>; +export const MAT_SNACK_BAR_DEFAULT_OPTIONS: InjectionToken>; // @public export class MatSnackBar implements OnDestroy { @@ -45,10 +45,10 @@ export class MatSnackBar implements OnDestroy { // (undocumented) ngOnDestroy(): void; open(message: string, action?: string, config?: MatSnackBarConfig): MatSnackBarRef; - get _openedSnackBarRef(): MatSnackBarRef | null; - set _openedSnackBarRef(value: MatSnackBarRef | null); - openFromComponent(component: ComponentType, config?: MatSnackBarConfig): MatSnackBarRef; - openFromTemplate(template: TemplateRef, config?: MatSnackBarConfig): MatSnackBarRef>; + get _openedSnackBarRef(): MatSnackBarRef | null; + set _openedSnackBarRef(value: MatSnackBarRef | null); + openFromComponent(component: ComponentType, config?: MatSnackBarConfig): MatSnackBarRef; + openFromTemplate(template: TemplateRef, config?: MatSnackBarConfig): MatSnackBarRef>; simpleSnackBarComponent: typeof SimpleSnackBar; snackBarContainerComponent: typeof MatSnackBarContainer; // (undocumented) @@ -74,7 +74,7 @@ export class MatSnackBarActions { } // @public -export class MatSnackBarConfig { +export class MatSnackBarConfig { announcementMessage?: string; data?: D | null; direction?: Direction; @@ -168,7 +168,7 @@ export class SimpleSnackBar implements TextOnlySnackBar { constructor(...args: unknown[]); action(): void; // (undocumented) - data: any; + data: TextOnlySnackBarData; get hasAction(): boolean; // (undocumented) snackBarRef: MatSnackBarRef; @@ -183,16 +183,21 @@ export interface TextOnlySnackBar { // (undocumented) action: () => void; // (undocumented) - data: { - message: string; - action: string; - }; + data: TextOnlySnackBarData; // (undocumented) hasAction: boolean; // (undocumented) snackBarRef: MatSnackBarRef; } +// @public +export interface TextOnlySnackBarData { + // (undocumented) + action: string; + // (undocumented) + message: string; +} + // (No @packageDocumentation comment for this package) ``` diff --git a/goldens/material/stepper/index.api.md b/goldens/material/stepper/index.api.md index 89debf3c8a63..c9661064d98e 100644 --- a/goldens/material/stepper/index.api.md +++ b/goldens/material/stepper/index.api.md @@ -50,14 +50,14 @@ export class MatStep extends CdkStep implements ErrorStateMatcher, AfterContentI } // @public -export class MatStepContent { +export class MatStepContent { constructor(...args: unknown[]); // (undocumented) - _template: TemplateRef; + _template: TemplateRef; // (undocumented) - static ɵdir: i0.ɵɵDirectiveDeclaration; + static ɵdir: i0.ɵɵDirectiveDeclaration, "ng-template[matStepContent]", never, {}, {}, never, never, true, never>; // (undocumented) - static ɵfac: i0.ɵɵFactoryDeclaration; + static ɵfac: i0.ɵɵFactoryDeclaration, never>; } // @public (undocumented) diff --git a/goldens/material/timepicker/index.api.md b/goldens/material/timepicker/index.api.md index 29b17a051d43..4176fd9e10a2 100644 --- a/goldens/material/timepicker/index.api.md +++ b/goldens/material/timepicker/index.api.md @@ -109,7 +109,7 @@ export class MatTimepickerInput implements MatTimepickerConnectedInput, Co // (undocumented) ngOnDestroy(): void; readonly openOnClick: InputSignalWithTransform; - registerOnChange(fn: (value: any) => void): void; + registerOnChange(fn: (value: unknown) => void): void; registerOnTouched(fn: () => void): void; registerOnValidatorChange(fn: () => void): void; setDisabledState(isDisabled: boolean): void; @@ -117,7 +117,7 @@ export class MatTimepickerInput implements MatTimepickerConnectedInput, Co timepickerValueAssigned(value: D | null): void; validate(control: AbstractControl): ValidationErrors | null; readonly value: ModelSignal; - writeValue(value: any): void; + writeValue(value: unknown): void; // (undocumented) static ɵdir: i0.ɵɵDirectiveDeclaration, "input[matTimepicker]", ["matTimepickerInput"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "timepicker": { "alias": "matTimepicker"; "required": true; "isSignal": true; }; "min": { "alias": "matTimepickerMin"; "required": false; "isSignal": true; }; "max": { "alias": "matTimepickerMax"; "required": false; "isSignal": true; }; "openOnClick": { "alias": "matTimepickerOpenOnClick"; "required": false; "isSignal": true; }; "disabledInput": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>; // (undocumented) diff --git a/goldens/material/tooltip/index.api.md b/goldens/material/tooltip/index.api.md index 5b3a661ac3c2..fadab81be148 100644 --- a/goldens/material/tooltip/index.api.md +++ b/goldens/material/tooltip/index.api.md @@ -76,10 +76,10 @@ export class MatTooltip implements OnDestroy, AfterViewInit { y: number; }): void; get tooltipClass(): string | string[] | Set | { - [key: string]: any; + [key: string]: unknown; }; set tooltipClass(value: string | string[] | Set | { - [key: string]: any; + [key: string]: unknown; }); // (undocumented) _tooltipInstance: TooltipComponent | null; @@ -143,7 +143,7 @@ export class TooltipComponent implements OnDestroy { show(delay: number): void; _tooltip: ElementRef; tooltipClass: string | string[] | Set | { - [key: string]: any; + [key: string]: unknown; }; _triggerElement: HTMLElement; // (undocumented) diff --git a/src/material/snack-bar/simple-snack-bar.ts b/src/material/snack-bar/simple-snack-bar.ts index 09070641000e..e9541d04444f 100644 --- a/src/material/snack-bar/simple-snack-bar.ts +++ b/src/material/snack-bar/simple-snack-bar.ts @@ -12,12 +12,18 @@ import {MatSnackBarRef} from './snack-bar-ref'; import {MAT_SNACK_BAR_DATA} from './snack-bar-config'; import {MatSnackBarAction, MatSnackBarActions, MatSnackBarLabel} from './snack-bar-content'; +/** Input data for a simple snack bar component that has a message and a single action. */ +export interface TextOnlySnackBarData { + message: string; + action: string; +} + /** * Interface for a simple snack bar component that has a message and a single action. */ export interface TextOnlySnackBar { - data: {message: string; action: string}; - snackBarRef: MatSnackBarRef; + data: TextOnlySnackBarData; + snackBarRef: MatSnackBarRef; action: () => void; hasAction: boolean; } @@ -35,8 +41,8 @@ export interface TextOnlySnackBar { }, }) export class SimpleSnackBar implements TextOnlySnackBar { - snackBarRef = inject>(MatSnackBarRef); - data = inject(MAT_SNACK_BAR_DATA); + snackBarRef = inject>(MatSnackBarRef); + data = inject(MAT_SNACK_BAR_DATA); constructor(...args: unknown[]); constructor() {} diff --git a/src/material/snack-bar/snack-bar-config.ts b/src/material/snack-bar/snack-bar-config.ts index 3ea23b9d8255..89dbe61b157c 100644 --- a/src/material/snack-bar/snack-bar-config.ts +++ b/src/material/snack-bar/snack-bar-config.ts @@ -11,7 +11,7 @@ import {AriaLivePoliteness} from '@angular/cdk/a11y'; import {Direction} from '@angular/cdk/bidi'; /** Injection token that can be used to access the data that was passed in to a snack bar. */ -export const MAT_SNACK_BAR_DATA = new InjectionToken('MatSnackBarData'); +export const MAT_SNACK_BAR_DATA = new InjectionToken('MatSnackBarData'); /** Possible values for horizontalPosition on MatSnackBarConfig. */ export type MatSnackBarHorizontalPosition = 'start' | 'center' | 'end' | 'left' | 'right'; @@ -22,7 +22,7 @@ export type MatSnackBarVerticalPosition = 'top' | 'bottom'; /** * Configuration used when opening a snack-bar. */ -export class MatSnackBarConfig { +export class MatSnackBarConfig { /** The politeness level for the MatAriaLiveAnnouncer announcement. */ politeness?: AriaLivePoliteness = 'polite'; diff --git a/src/material/snack-bar/snack-bar-container.ts b/src/material/snack-bar/snack-bar-container.ts index 5aa873d9ab83..f40c774114e2 100644 --- a/src/material/snack-bar/snack-bar-container.ts +++ b/src/material/snack-bar/snack-bar-container.ts @@ -63,13 +63,13 @@ const EXIT_ANIMATION = '_mat-snack-bar-exit'; '(animationcancel)': 'onAnimationEnd($event.animationName)', }, }) -export class MatSnackBarContainer extends BasePortalOutlet implements OnDestroy { +export class MatSnackBarContainer extends BasePortalOutlet implements OnDestroy { private _ngZone = inject(NgZone); readonly _elementRef = inject>(ElementRef); private _changeDetectorRef = inject(ChangeDetectorRef); private _platform = inject(Platform); protected _animationsDisabled = _animationsDisabled(); - snackBarConfig = inject(MatSnackBarConfig); + snackBarConfig = inject>(MatSnackBarConfig); private _document = inject(DOCUMENT); private _trackedModals = new Set(); diff --git a/src/material/snack-bar/snack-bar-ref.ts b/src/material/snack-bar/snack-bar-ref.ts index b5eaad9ab629..652aa4b6273b 100644 --- a/src/material/snack-bar/snack-bar-ref.ts +++ b/src/material/snack-bar/snack-bar-ref.ts @@ -22,7 +22,7 @@ const MAX_TIMEOUT = Math.pow(2, 31) - 1; /** * Reference to a snack bar dispatched from the snack bar service. */ -export class MatSnackBarRef { +export class MatSnackBarRef { /** The instance of the component making up the content of the snack bar. */ instance: T; @@ -30,7 +30,7 @@ export class MatSnackBarRef { * The instance of the component making up the content of the snack bar. * @docs-private */ - containerInstance: MatSnackBarContainer; + containerInstance: MatSnackBarContainer; /** Subject for notifying the user that the snack bar has been dismissed. */ private readonly _afterDismissed = new Subject(); @@ -51,7 +51,7 @@ export class MatSnackBarRef { private _dismissedByAction = false; constructor( - containerInstance: MatSnackBarContainer, + containerInstance: MatSnackBarContainer, private _overlayRef: OverlayRef, ) { this.containerInstance = containerInstance; diff --git a/src/material/snack-bar/snack-bar.spec.ts b/src/material/snack-bar/snack-bar.spec.ts index 809921926b4f..3b14d8f9fcd0 100644 --- a/src/material/snack-bar/snack-bar.spec.ts +++ b/src/material/snack-bar/snack-bar.spec.ts @@ -19,7 +19,7 @@ import { MatSnackBarRef, SimpleSnackBar, } from './index'; -import {MAT_SNACK_BAR_DEFAULT_OPTIONS} from './snack-bar'; +import {MAT_SNACK_BAR_DEFAULT_OPTIONS, SnackBarTemplateContext} from './snack-bar'; import {MATERIAL_ANIMATIONS} from '../core'; describe('MatSnackBar', () => { @@ -571,7 +571,10 @@ describe('MatSnackBar', () => { }); it('should inject the snack bar reference into the component', () => { - const snackBarRef = snackBar.openFromComponent(BurritosNotification); + const snackBarRef = snackBar.openFromComponent< + BurritosNotification, + BurritosNotificationData + >(BurritosNotification); expect(snackBarRef.instance.snackBarRef) .withContext('Expected component to have an injected snack bar reference.') @@ -585,10 +588,11 @@ describe('MatSnackBar', () => { }); it('should be able to inject arbitrary user data', () => { + const data: BurritosNotificationData = { + burritoType: 'Chimichanga', + }; const snackBarRef = snackBar.openFromComponent(BurritosNotification, { - data: { - burritoType: 'Chimichanga', - }, + data, }); expect(snackBarRef.instance.data) @@ -997,17 +1001,22 @@ class ComponentWithChildViewContainer { `, }) class ComponentWithTemplateRef { - @ViewChild(TemplateRef) templateRef: TemplateRef; + @ViewChild(TemplateRef) templateRef: TemplateRef>; localValue: string; } +interface BurritosNotificationData { + burritoType: string; +} + /** Simple component for testing ComponentPortal. */ @Component({ template: '

Burritos are on the way.

', }) class BurritosNotification { - snackBarRef = inject>(MatSnackBarRef); - data = inject(MAT_SNACK_BAR_DATA); + snackBarRef = + inject>(MatSnackBarRef); + data = inject(MAT_SNACK_BAR_DATA); } @Component({ diff --git a/src/material/snack-bar/snack-bar.ts b/src/material/snack-bar/snack-bar.ts index 5ebca0059f8f..b123288e00b4 100644 --- a/src/material/snack-bar/snack-bar.ts +++ b/src/material/snack-bar/snack-bar.ts @@ -25,7 +25,7 @@ import { TemplateRef, inject, } from '@angular/core'; -import {SimpleSnackBar, TextOnlySnackBar} from './simple-snack-bar'; +import {SimpleSnackBar, TextOnlySnackBar, TextOnlySnackBarData} from './simple-snack-bar'; import {MatSnackBarContainer} from './snack-bar-container'; import {MAT_SNACK_BAR_DATA, MatSnackBarConfig} from './snack-bar-config'; import {MatSnackBarRef} from './snack-bar-ref'; @@ -34,7 +34,7 @@ import {takeUntil} from 'rxjs/operators'; import {_animationsDisabled} from '../core'; /** Injection token that can be used to specify default snack bar. */ -export const MAT_SNACK_BAR_DEFAULT_OPTIONS = new InjectionToken( +export const MAT_SNACK_BAR_DEFAULT_OPTIONS = new InjectionToken>( 'mat-snack-bar-default-options', { providedIn: 'root', @@ -42,6 +42,11 @@ export const MAT_SNACK_BAR_DEFAULT_OPTIONS = new InjectionToken { + $implicit?: D | null; + snackBarRef?: MatSnackBarRef>, D>; +} + /** * Service to dispatch Material Design snack bar messages. */ @@ -59,7 +64,7 @@ export class MatSnackBar implements OnDestroy { * If there is a parent snack-bar service, all operations should delegate to that parent * via `_openedSnackBarRef`. */ - private _snackBarRefAtThisLevel: MatSnackBarRef | null = null; + private _snackBarRefAtThisLevel: MatSnackBarRef | null = null; /** The component that should be rendered as the snack bar's simple component. */ simpleSnackBarComponent = SimpleSnackBar; @@ -71,12 +76,12 @@ export class MatSnackBar implements OnDestroy { handsetCssClass = 'mat-mdc-snack-bar-handset'; /** Reference to the currently opened snackbar at *any* level. */ - get _openedSnackBarRef(): MatSnackBarRef | null { + get _openedSnackBarRef(): MatSnackBarRef | null { const parent = this._parentSnackBar; return parent ? parent._openedSnackBarRef : this._snackBarRefAtThisLevel; } - set _openedSnackBarRef(value: MatSnackBarRef | null) { + set _openedSnackBarRef(value: MatSnackBarRef | null) { if (this._parentSnackBar) { this._parentSnackBar._openedSnackBarRef = value; } else { @@ -94,11 +99,11 @@ export class MatSnackBar implements OnDestroy { * @param component Component to be instantiated. * @param config Extra configuration for the snack bar. */ - openFromComponent( + openFromComponent( component: ComponentType, config?: MatSnackBarConfig, - ): MatSnackBarRef { - return this._attach(component, config) as MatSnackBarRef; + ): MatSnackBarRef { + return this._attach(component, config); } /** @@ -108,10 +113,10 @@ export class MatSnackBar implements OnDestroy { * @param template Template to be instantiated. * @param config Extra configuration for the snack bar. */ - openFromTemplate( - template: TemplateRef, - config?: MatSnackBarConfig, - ): MatSnackBarRef> { + openFromTemplate( + template: TemplateRef>, + config?: MatSnackBarConfig, + ): MatSnackBarRef>, D> { return this._attach(template, config); } @@ -124,13 +129,18 @@ export class MatSnackBar implements OnDestroy { open( message: string, action: string = '', - config?: MatSnackBarConfig, - ): MatSnackBarRef { - const _config = {...this._defaultConfig, ...config}; - - // Since the user doesn't have access to the component, we can - // override the data to pass in our own message and action. - _config.data = {message, action}; + config?: MatSnackBarConfig, + ): MatSnackBarRef { + const _config: MatSnackBarConfig = { + ...this._defaultConfig, + ...config, + // Since the user doesn't have access to the component, we can + // override the data to pass in our own message and action. + data: { + message, + action, + }, + }; // Since the snack bar has `role="alert"`, we don't // want to announce the same message twice. @@ -160,10 +170,10 @@ export class MatSnackBar implements OnDestroy { /** * Attaches the snack bar container component to the overlay. */ - private _attachSnackBarContainer( + private _attachSnackBarContainer( overlayRef: OverlayRef, - config: MatSnackBarConfig, - ): MatSnackBarContainer { + config: MatSnackBarConfig, + ): MatSnackBarContainer { const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector; const injector = Injector.create({ parent: userInjector || this._injector, @@ -171,11 +181,11 @@ export class MatSnackBar implements OnDestroy { }); const containerPortal = new ComponentPortal( - this.snackBarContainerComponent, + this.snackBarContainerComponent as typeof MatSnackBarContainer, config.viewContainerRef, injector, ); - const containerRef: ComponentRef = overlayRef.attach(containerPortal); + const containerRef: ComponentRef> = overlayRef.attach(containerPortal); containerRef.instance.snackBarConfig = config; return containerRef.instance; } @@ -183,26 +193,41 @@ export class MatSnackBar implements OnDestroy { /** * Places a new component or a template as the content of the snack bar container. */ - private _attach( - content: ComponentType | TemplateRef, - userConfig?: MatSnackBarConfig, - ): MatSnackBarRef> { - const config = {...new MatSnackBarConfig(), ...this._defaultConfig, ...userConfig}; + private _attach( + content: ComponentType, + userConfig?: MatSnackBarConfig, + ): MatSnackBarRef; + private _attach( + content: TemplateRef>, + userConfig?: MatSnackBarConfig, + ): MatSnackBarRef>, D>; + private _attach( + content: ComponentType | TemplateRef>, + userConfig?: MatSnackBarConfig, + ): MatSnackBarRef>, D> { + const config: MatSnackBarConfig = { + ...new MatSnackBarConfig(), + ...(this._defaultConfig as MatSnackBarConfig), + ...userConfig, + }; const overlayRef = this._createOverlay(config); const container = this._attachSnackBarContainer(overlayRef, config); - const snackBarRef = new MatSnackBarRef>(container, overlayRef); + const snackBarRef = new MatSnackBarRef>, D>( + container, + overlayRef, + ); if (content instanceof TemplateRef) { - const portal = new TemplatePortal(content, null!, { + const portal = new TemplatePortal>(content, null!, { $implicit: config.data, - snackBarRef, - } as any); + snackBarRef: snackBarRef as MatSnackBarRef>, D>, + }); snackBarRef.instance = container.attachTemplatePortal(portal); } else { const injector = this._createInjector(config, snackBarRef); const portal = new ComponentPortal(content, undefined, injector); - const contentRef = container.attachComponentPortal(portal); + const contentRef = container.attachComponentPortal(portal); // We can't pass this via the injector, because the injector is created earlier. snackBarRef.instance = contentRef.instance; @@ -227,11 +252,11 @@ export class MatSnackBar implements OnDestroy { this._animateSnackBar(snackBarRef, config); this._openedSnackBarRef = snackBarRef; - return this._openedSnackBarRef; + return snackBarRef; } /** Animates the old snack bar out and the new one in. */ - private _animateSnackBar(snackBarRef: MatSnackBarRef, config: MatSnackBarConfig) { + private _animateSnackBar(snackBarRef: MatSnackBarRef, config: MatSnackBarConfig) { // When the snackbar is dismissed, clear the reference to it. snackBarRef.afterDismissed().subscribe(() => { // Clear the snackbar ref if it hasn't already been replaced by a newer snackbar. @@ -266,7 +291,7 @@ export class MatSnackBar implements OnDestroy { * Creates a new overlay and places it in the correct location. * @param config The user-specified snack bar config. */ - private _createOverlay(config: MatSnackBarConfig): OverlayRef { + private _createOverlay(config: MatSnackBarConfig): OverlayRef { const overlayConfig = new OverlayConfig(); overlayConfig.direction = config.direction; @@ -302,7 +327,10 @@ export class MatSnackBar implements OnDestroy { * @param config Config that was used to create the snack bar. * @param snackBarRef Reference to the snack bar. */ - private _createInjector(config: MatSnackBarConfig, snackBarRef: MatSnackBarRef): Injector { + private _createInjector( + config: MatSnackBarConfig, + snackBarRef: MatSnackBarRef, + ): Injector { const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector; return Injector.create({ diff --git a/src/material/sort/sort.spec.ts b/src/material/sort/sort.spec.ts index 10181b65bf72..a5a3e3e94fa5 100644 --- a/src/material/sort/sort.spec.ts +++ b/src/material/sort/sort.spec.ts @@ -504,8 +504,8 @@ class SimpleMatSortApp { } } -class FakeDataSource extends DataSource { - connect(collectionViewer: CollectionViewer): Observable { +class FakeDataSource extends DataSource { + connect(collectionViewer: CollectionViewer): Observable { return collectionViewer.viewChange.pipe(map(() => [])); } disconnect() {} diff --git a/src/material/stepper/step-content.ts b/src/material/stepper/step-content.ts index 8328c0d10f5e..569f22e23fb3 100644 --- a/src/material/stepper/step-content.ts +++ b/src/material/stepper/step-content.ts @@ -14,8 +14,8 @@ import {Directive, TemplateRef, inject} from '@angular/core'; @Directive({ selector: 'ng-template[matStepContent]', }) -export class MatStepContent { - _template = inject>(TemplateRef); +export class MatStepContent { + _template = inject>(TemplateRef); constructor(...args: unknown[]); constructor() {} diff --git a/src/material/table/table-data-source.ts b/src/material/table/table-data-source.ts index 81c16d3acd14..dcd9435916c7 100644 --- a/src/material/table/table-data-source.ts +++ b/src/material/table/table-data-source.ts @@ -229,10 +229,14 @@ export class MatTableDataSource extend * @returns Whether the filter matches against the data */ filterPredicate: (data: T, filter: string) => boolean = (data: T, filter: string): boolean => { + if ((typeof ngDevMode === 'undefined' || ngDevMode) && typeof data !== 'object') { + throw new Error('Default implementation of filterPredicate requires data to be object.'); + } + // Transform the filter by converting it to lowercase and removing whitespace. const transformedFilter = filter.trim().toLowerCase(); // Loops over the values in the array and returns true if any of them match the filter string - return Object.values(data as {[key: string]: any}).some(value => + return Object.values(data as object).some(value => `${value}`.toLowerCase().includes(transformedFilter), ); }; diff --git a/src/material/table/table.spec.ts b/src/material/table/table.spec.ts index ef9b41b31f17..6b03b81bfe38 100644 --- a/src/material/table/table.spec.ts +++ b/src/material/table/table.spec.ts @@ -16,9 +16,9 @@ describe('MatTable', () => { const data = fixture.componentInstance.dataSource!.data; expectTableToMatchContent(tableElement, [ ['Column A', 'Column B', 'Column C'], - [data[0].a, data[0].b, data[0].c], - [data[1].a, data[1].b, data[1].c], - [data[2].a, data[2].b, data[2].c], + [data[0].a, data[0].b, data[0].c] as string[], + [data[1].a, data[1].b, data[1].c] as string[], + [data[2].a, data[2].b, data[2].c] as string[], ['fourth_row'], ['Footer A', 'Footer B', 'Footer C'], ]); @@ -64,10 +64,10 @@ describe('MatTable', () => { const data = fixture.componentInstance.dataSource!.data; expectTableToMatchContent(tableElement, [ ['Column A', 'Column B', 'Column C'], - [data[0].a, data[0].b, data[0].c], - [data[1].a, data[1].b, data[1].c], - [data[2].a, data[2].b, data[2].c], - [data[3].a, data[3].b, data[3].c], + [data[0].a, data[0].b, data[0].c] as string[], + [data[1].a, data[1].b, data[1].c] as string[], + [data[2].a, data[2].b, data[2].c] as string[], + [data[3].a, data[3].b, data[3].c] as string[], ]); }); @@ -159,9 +159,9 @@ describe('MatTable', () => { const data = fixture.componentInstance.dataSource!.data; expectTableToMatchContent(tableElement, [ ['Column A', 'Column B', 'Column C'], - [data[0].a, data[0].b, data[0].c], - [data[1].a, data[1].b, data[1].c], - [data[2].a, data[2].b, data[2].c], + [data[0].a, data[0].b, data[0].c] as string[], + [data[1].a, data[1].b, data[1].c] as string[], + [data[2].a, data[2].b, data[2].c] as string[], ]); }); @@ -173,9 +173,9 @@ describe('MatTable', () => { const data = fixture.componentInstance.dataSource!.data; expectTableToMatchContent(tableElement, [ ['Column A', 'Column B', 'Column C'], - [data[0].a, data[0].b, data[0].c], - [data[1].a, data[1].b, data[1].c], - [data[2].a, data[2].b, data[2].c], + [data[0].a, data[0].b, data[0].c] as string[], + [data[1].a, data[1].b, data[1].c] as string[], + [data[2].a, data[2].b, data[2].c] as string[], ]); }); @@ -357,7 +357,7 @@ describe('MatTable', () => { ]); // Change the filter to a falsy value that might come in from the view. - dataSource.filter = 0 as any; + dataSource.filter = 0 as unknown as string; flushMicrotasks(); fixture.detectChanges(); expectTableToMatchContent(tableElement, [ @@ -604,7 +604,7 @@ describe('MatTable', () => { ['Footer A', 'Footer B', 'Footer C'], ]); - dataSource.data = {} as any; + dataSource.data = {} as TestData[]; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expectTableToMatchContent(tableElement, [ @@ -1108,7 +1108,7 @@ function getActualTableContent(tableElement: Element): string[][] { return actualTableContent.map(row => row.map(cell => cell.textContent!.trim())); } -export function expectTableToMatchContent(tableElement: Element, expected: any[]) { +export function expectTableToMatchContent(tableElement: Element, expected: string[][]) { const missedExpectations: string[] = []; function checkCellContent(actualCell: string, expectedCell: string) { if (actualCell !== expectedCell) { @@ -1134,7 +1134,7 @@ export function expectTableToMatchContent(tableElement: Element, expected: any[] } row.forEach((actualCell, cellIndex) => { - const expectedCell = expectedRow ? expectedRow[cellIndex] : null; + const expectedCell = expectedRow[cellIndex]; checkCellContent(actualCell, expectedCell); }); }); diff --git a/src/material/timepicker/timepicker-input.ts b/src/material/timepicker/timepicker-input.ts index 656860228778..754bd01710f4 100644 --- a/src/material/timepicker/timepicker-input.ts +++ b/src/material/timepicker/timepicker-input.ts @@ -88,7 +88,7 @@ export class MatTimepickerInput private _dateFormats = inject(MAT_DATE_FORMATS, {optional: true})!; private _formField = inject(MAT_FORM_FIELD, {optional: true}); - private _onChange: ((value: any) => void) | undefined; + private _onChange: ((value: unknown) => void) | undefined; private _onTouched: (() => void) | undefined; private _validatorOnChange: (() => void) | undefined; private _cleanupClick: () => void; @@ -195,7 +195,7 @@ export class MatTimepickerInput * Implemented as a part of `ControlValueAccessor`. * @docs-private */ - writeValue(value: any): void { + writeValue(value: unknown): void { // Note that we need to deserialize here, rather than depend on the value change effect, // because `getValidDateOrNull` will clobber the value if it's parseable, but not created by // the current adapter (see #30140). @@ -207,7 +207,7 @@ export class MatTimepickerInput * Implemented as a part of `ControlValueAccessor`. * @docs-private */ - registerOnChange(fn: (value: any) => void): void { + registerOnChange(fn: (value: unknown) => void): void { this._onChange = fn; } diff --git a/src/material/tooltip/tooltip.spec.ts b/src/material/tooltip/tooltip.spec.ts index 3509ff5fbd96..3c515043f191 100644 --- a/src/material/tooltip/tooltip.spec.ts +++ b/src/material/tooltip/tooltip.spec.ts @@ -1386,7 +1386,7 @@ describe('MatTooltip', () => { fixture.detectChanges(); const styles = fixture.nativeElement.querySelector('button').style; - expect(styles.touchAction || (styles as any).webkitUserDrag).toBe('none'); + expect(styles.touchAction || styles.webkitUserDrag).toBe('none'); }); it('should allow native touch interactions if touch gestures are turned off', () => { @@ -1395,7 +1395,7 @@ describe('MatTooltip', () => { fixture.detectChanges(); const styles = fixture.nativeElement.querySelector('button').style; - expect(styles.touchAction || (styles as any).webkitUserDrag).toBeFalsy(); + expect(styles.touchAction || styles.webkitUserDrag).toBeFalsy(); }); it('should allow text selection on inputs when gestures are set to auto', () => { @@ -1407,13 +1407,13 @@ describe('MatTooltip', () => { expect(inputStyle.userSelect).toBeFalsy(); expect(inputStyle.webkitUserSelect).toBeFalsy(); - expect((inputStyle as any).msUserSelect).toBeFalsy(); - expect((inputStyle as any).MozUserSelect).toBeFalsy(); + expect(inputStyle.msUserSelect).toBeFalsy(); + expect(inputStyle.MozUserSelect).toBeFalsy(); expect(textareaStyle.userSelect).toBeFalsy(); expect(textareaStyle.webkitUserSelect).toBeFalsy(); - expect((textareaStyle as any).msUserSelect).toBeFalsy(); - expect((textareaStyle as any).MozUserSelect).toBeFalsy(); + expect(textareaStyle.msUserSelect).toBeFalsy(); + expect(textareaStyle.MozUserSelect).toBeFalsy(); }); it('should disable text selection on inputs when gestures are set to on', () => { @@ -1425,14 +1425,14 @@ describe('MatTooltip', () => { const inputUserSelect = inputStyle.userSelect || inputStyle.webkitUserSelect || - (inputStyle as any).msUserSelect || - (inputStyle as any).MozUserSelect; + inputStyle.msUserSelect || + inputStyle.MozUserSelect; const textareaStyle = fixture.componentInstance.textarea.nativeElement.style; const textareaUserSelect = textareaStyle.userSelect || textareaStyle.webkitUserSelect || - (textareaStyle as any).msUserSelect || - (textareaStyle as any).MozUserSelect; + textareaStyle.msUserSelect || + textareaStyle.MozUserSelect; expect(inputUserSelect).toBe('none'); expect(textareaUserSelect).toBe('none'); @@ -1570,7 +1570,7 @@ describe('MatTooltip', () => { }) class BasicTooltipDemo { position: TooltipPosition = 'below'; - message: any = initialTooltipMessage; + message: string | number = initialTooltipMessage; showButton = true; showTooltipClass = false; tooltipDisabled = false; @@ -1683,7 +1683,7 @@ class TooltipOnDraggableElement { imports: [MatTooltip], }) class TooltipDemoWithoutPositionBinding { - message: any = initialTooltipMessage; + message: string = initialTooltipMessage; @ViewChild(MatTooltip) tooltip: MatTooltip; @ViewChild('button') button: ElementRef; } @@ -1705,7 +1705,7 @@ class TooltipDemoWithoutTooltipClassBinding { imports: [MatTooltip], }) class TooltipDemoWithTooltipClassBinding { - message: any = initialTooltipMessage; + message: string = initialTooltipMessage; @ViewChild(MatTooltip) tooltip: MatTooltip; @ViewChild('button') button: ElementRef; } diff --git a/src/material/tooltip/tooltip.ts b/src/material/tooltip/tooltip.ts index a3c6f63751f0..996ade691b04 100644 --- a/src/material/tooltip/tooltip.ts +++ b/src/material/tooltip/tooltip.ts @@ -55,6 +55,15 @@ import {ComponentPortal} from '@angular/cdk/portal'; import {Observable, Subject} from 'rxjs'; import {_animationsDisabled} from '../core'; +declare global { + interface CSSStyleDeclaration { + msUserSelect: string; + MozUserSelect: string; + webkitUserDrag: string; + webkitTapHighlightColor: string; + } +} + /** Possible positions for a tooltip. */ export type TooltipPosition = 'left' | 'right' | 'above' | 'below' | 'before' | 'after'; @@ -194,7 +203,7 @@ export class MatTooltip implements OnDestroy, AfterViewInit { private _position: TooltipPosition = 'below'; private _positionAtOrigin: boolean = false; private _disabled: boolean = false; - private _tooltipClass: string | string[] | Set | {[key: string]: any}; + private _tooltipClass: string | string[] | Set | {[key: string]: unknown}; private _viewInitialized = false; private _pointerExitEventsInitialized = false; private readonly _tooltipComponent = TooltipComponent; @@ -336,7 +345,7 @@ export class MatTooltip implements OnDestroy, AfterViewInit { return this._tooltipClass; } - set tooltipClass(value: string | string[] | Set | {[key: string]: any}) { + set tooltipClass(value: string | string[] | Set | {[key: string]: unknown}) { this._tooltipClass = value; if (this._tooltipInstance) { this._setTooltipClass(this._tooltipClass); @@ -701,7 +710,9 @@ export class MatTooltip implements OnDestroy, AfterViewInit { } /** Updates the tooltip class */ - private _setTooltipClass(tooltipClass: string | string[] | Set | {[key: string]: any}) { + private _setTooltipClass( + tooltipClass: string | string[] | Set | {[key: string]: unknown}, + ) { if (this._tooltipInstance) { this._tooltipInstance.tooltipClass = tooltipClass; this._tooltipInstance._markForCheck(); @@ -889,20 +900,20 @@ export class MatTooltip implements OnDestroy, AfterViewInit { // textareas, because it prevents the user from typing into them on iOS Safari. if (gestures === 'on' || (element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA')) { style.userSelect = - (style as any).msUserSelect = + style.msUserSelect = style.webkitUserSelect = - (style as any).MozUserSelect = + style.MozUserSelect = 'none'; } // If we have `auto` gestures and the element uses native HTML dragging, // we don't set `-webkit-user-drag` because it prevents the native behavior. if (gestures === 'on' || !element.draggable) { - (style as any).webkitUserDrag = 'none'; + style.webkitUserDrag = 'none'; } style.touchAction = 'none'; - (style as any).webkitTapHighlightColor = 'transparent'; + style.webkitTapHighlightColor = 'transparent'; } } @@ -963,7 +974,7 @@ export class TooltipComponent implements OnDestroy { message: string; /** Classes to be added to the tooltip. Supports the same syntax as `ngClass`. */ - tooltipClass: string | string[] | Set | {[key: string]: any}; + tooltipClass: string | string[] | Set | {[key: string]: unknown}; /** The timeout ID of any current timer set to show the tooltip */ private _showTimeoutId: ReturnType | undefined; diff --git a/src/material/tree/node.ts b/src/material/tree/node.ts index ef7c17a1d970..d88c18db27e1 100644 --- a/src/material/tree/node.ts +++ b/src/material/tree/node.ts @@ -31,7 +31,7 @@ import {NoopTreeKeyManager, TreeKeyManagerItem, TreeKeyManagerStrategy} from '@a function isNoopTreeKeyManager( keyManager: TreeKeyManagerStrategy, ): keyManager is NoopTreeKeyManager { - return !!(keyManager as any)._isNoopTreeKeyManager; + return !!(keyManager as NoopTreeKeyManager)._isNoopTreeKeyManager; } /** diff --git a/src/material/tree/tree-using-tree-control.spec.ts b/src/material/tree/tree-using-tree-control.spec.ts index b44b11f9f2b8..1d51cdfe4360 100644 --- a/src/material/tree/tree-using-tree-control.spec.ts +++ b/src/material/tree/tree-using-tree-control.spec.ts @@ -19,6 +19,9 @@ import { MatTreeNestedDataSource, } from './index'; +type NodeContent = string[]; +type TreeContent = NodeContent[]; + describe('MatTree', () => { /** Represents an indent for expectNestedTreeToMatch */ const _ = {}; @@ -754,11 +757,11 @@ function getNodes(treeElement: Element): HTMLElement[] { function expectFlatTreeToMatch( treeElement: Element, expectedPaddingIndent: number = 28, - ...expectedTree: any[] + ...expectedTree: TreeContent ) { const missedExpectations: string[] = []; - function checkNode(node: Element, expectedNode: any[]) { + function checkNode(node: Element, expectedNode: NodeContent) { const actualTextContent = node.textContent!.trim(); const expectedTextContent = expectedNode[expectedNode.length - 1]; if (actualTextContent !== expectedTextContent) { @@ -768,7 +771,7 @@ function expectFlatTreeToMatch( } } - function checkLevel(node: Element, expectedNode: any[]) { + function checkLevel(node: Element, expectedNode: NodeContent) { const rawLevel = (node as HTMLElement).style.paddingLeft; // Some browsers return 0, while others return 0px. @@ -788,7 +791,7 @@ function expectFlatTreeToMatch( } getNodes(treeElement).forEach((node, index) => { - const expected = expectedTree ? expectedTree[index] : null; + const expected = expectedTree[index]; checkLevel(node, expected); checkNode(node, expected); @@ -799,9 +802,9 @@ function expectFlatTreeToMatch( } } -function expectNestedTreeToMatch(treeElement: Element, ...expectedTree: any[]) { +function expectNestedTreeToMatch(treeElement: Element, ...expectedTree: TreeContent) { const missedExpectations: string[] = []; - function checkNodeContent(node: Element, expectedNode: any[]) { + function checkNodeContent(node: Element, expectedNode: NodeContent) { const expectedTextContent = expectedNode[expectedNode.length - 1]; const actualTextContent = node.childNodes.item(0).textContent!.trim(); if (actualTextContent !== expectedTextContent) { @@ -811,7 +814,7 @@ function expectNestedTreeToMatch(treeElement: Element, ...expectedTree: any[]) { } } - function checkNodeDescendants(node: Element, expectedNode: any[], currentIndex: number) { + function checkNodeDescendants(node: Element, expectedNode: NodeContent, currentIndex: number) { let expectedDescendant = 0; for (let i = currentIndex + 1; i < expectedTree.length; ++i) { @@ -831,7 +834,7 @@ function expectNestedTreeToMatch(treeElement: Element, ...expectedTree: any[]) { } getNodes(treeElement).forEach((node, index) => { - const expected = expectedTree ? expectedTree[index] : null; + const expected = expectedTree[index]; checkNodeDescendants(node, expected, index); checkNodeContent(node, expected); diff --git a/src/material/tree/tree.spec.ts b/src/material/tree/tree.spec.ts index b85f68b84543..b003c388d03f 100644 --- a/src/material/tree/tree.spec.ts +++ b/src/material/tree/tree.spec.ts @@ -12,6 +12,9 @@ import {BehaviorSubject, Observable} from 'rxjs'; import {map} from 'rxjs/operators'; import {MatTree, MatTreeModule, MatTreeNestedDataSource} from './index'; +type NodeContent = string[]; +type TreeContent = NodeContent[]; + describe('MatTree', () => { /** Represents an indent for expectNestedTreeToMatch */ const _ = {}; @@ -756,11 +759,11 @@ function getNodes(treeElement: Element): HTMLElement[] { function expectFlatTreeToMatch( treeElement: Element, expectedPaddingIndent: number = 28, - ...expectedTree: any[] + ...expectedTree: TreeContent ) { const missedExpectations: string[] = []; - function checkNode(node: Element, expectedNode: any[]) { + function checkNode(node: Element, expectedNode: NodeContent) { const actualTextContent = node.textContent!.trim(); const expectedTextContent = expectedNode[expectedNode.length - 1]; if (actualTextContent !== expectedTextContent) { @@ -770,7 +773,7 @@ function expectFlatTreeToMatch( } } - function checkLevel(node: Element, expectedNode: any[]) { + function checkLevel(node: Element, expectedNode: NodeContent) { const rawLevel = (node as HTMLElement).style.paddingLeft; // Some browsers return 0, while others return 0px. @@ -790,7 +793,7 @@ function expectFlatTreeToMatch( } getNodes(treeElement).forEach((node, index) => { - const expected = expectedTree ? expectedTree[index] : null; + const expected = expectedTree[index]; checkLevel(node, expected); checkNode(node, expected); @@ -801,9 +804,9 @@ function expectFlatTreeToMatch( } } -function expectNestedTreeToMatch(treeElement: Element, ...expectedTree: any[]) { +function expectNestedTreeToMatch(treeElement: Element, ...expectedTree: TreeContent) { const missedExpectations: string[] = []; - function checkNodeContent(node: Element, expectedNode: any[]) { + function checkNodeContent(node: Element, expectedNode: NodeContent) { const expectedTextContent = expectedNode[expectedNode.length - 1]; const actualTextContent = node.childNodes.item(0).textContent!.trim(); if (actualTextContent !== expectedTextContent) { @@ -813,7 +816,7 @@ function expectNestedTreeToMatch(treeElement: Element, ...expectedTree: any[]) { } } - function checkNodeDescendants(node: Element, expectedNode: any[], currentIndex: number) { + function checkNodeDescendants(node: Element, expectedNode: NodeContent, currentIndex: number) { let expectedDescendant = 0; for (let i = currentIndex + 1; i < expectedTree.length; ++i) { @@ -833,7 +836,7 @@ function expectNestedTreeToMatch(treeElement: Element, ...expectedTree: any[]) { } getNodes(treeElement).forEach((node, index) => { - const expected = expectedTree ? expectedTree[index] : null; + const expected = expectedTree[index]; checkNodeDescendants(node, expected, index); checkNodeContent(node, expected);