Skip to content

Commit d92f8f2

Browse files
authored
fix(material/core): update mixin functions to avoid unknown cast (#22577)
Reworks the mixin functions in order to remove a workaround where we had to cast to `unknown`. The cast was causing some issues with Closure compiler.
1 parent a92ad3d commit d92f8f2

File tree

9 files changed

+41
-41
lines changed

9 files changed

+41
-41
lines changed

src/material-experimental/mdc-chips/chip.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ export class MatChipCssInternalOnly { }
8888
* Boilerplate for applying mixins to MatChip.
8989
* @docs-private
9090
*/
91-
class MatChipBase {
91+
abstract class MatChipBase {
92+
abstract disabled: boolean;
9293
constructor(public _elementRef: ElementRef) {}
9394
}
9495

src/material/chips/chip.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ export const MAT_CHIP_TRAILING_ICON =
8989

9090
// Boilerplate for applying mixins to MatChip.
9191
/** @docs-private */
92-
class MatChipBase {
92+
abstract class MatChipBase {
93+
abstract disabled: boolean;
9394
constructor(public _elementRef: ElementRef) {}
9495
}
9596

src/material/core/common-behaviors/color.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Constructor} from './constructor';
9+
import {AbstractConstructor, Constructor} from './constructor';
1010
import {ElementRef} from '@angular/core';
1111

1212
/** @docs-private */
@@ -19,7 +19,7 @@ export interface CanColor {
1919
}
2020

2121
/** @docs-private */
22-
export type CanColorCtor = Constructor<CanColor>;
22+
export type CanColorCtor = Constructor<CanColor> & AbstractConstructor<CanColor>;
2323

2424
/** @docs-private */
2525
export interface HasElementRef {
@@ -30,6 +30,8 @@ export interface HasElementRef {
3030
export type ThemePalette = 'primary' | 'accent' | 'warn' | undefined;
3131

3232
/** Mixin to augment a directive with a `color` property. */
33+
export function mixinColor<T extends AbstractConstructor<HasElementRef>>(
34+
base: T, defaultColor?: ThemePalette): CanColorCtor & T;
3335
export function mixinColor<T extends Constructor<HasElementRef>>(
3436
base: T, defaultColor?: ThemePalette): CanColorCtor & T {
3537
return class extends base {

src/material/core/common-behaviors/constructor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ export type Constructor<T> = new(...args: any[]) => T;
1313
* This is a permissive type for abstract class constructors.
1414
* @docs-private
1515
*/
16-
export type AbstractConstructor<T> = Function & { prototype: T };
16+
export type AbstractConstructor<T = object> = abstract new (...args: any[]) => T;

src/material/core/common-behaviors/disable-ripple.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {coerceBooleanProperty} from '@angular/cdk/coercion';
10-
import {Constructor, AbstractConstructor} from './constructor';
10+
import {AbstractConstructor, Constructor} from './constructor';
1111

1212
/** @docs-private */
1313
export interface CanDisableRipple {
@@ -16,23 +16,20 @@ export interface CanDisableRipple {
1616
}
1717

1818
/** @docs-private */
19-
export type CanDisableRippleCtor = Constructor<CanDisableRipple>;
19+
export type CanDisableRippleCtor = Constructor<CanDisableRipple> &
20+
AbstractConstructor<CanDisableRipple>;
2021

2122
/** Mixin to augment a directive with a `disableRipple` property. */
22-
export function mixinDisableRipple<T extends AbstractConstructor<{}>>(
23-
base: T): CanDisableRippleCtor & T {
24-
abstract class Mixin extends (base as unknown as Constructor<{}>) {
23+
export function mixinDisableRipple<T extends AbstractConstructor<{}>>(base: T):
24+
CanDisableRippleCtor & T;
25+
export function mixinDisableRipple<T extends Constructor<{}>>(base: T): CanDisableRippleCtor & T {
26+
return class extends base {
2527
private _disableRipple: boolean = false;
2628

2729
/** Whether the ripple effect is disabled or not. */
2830
get disableRipple() { return this._disableRipple; }
2931
set disableRipple(value: any) { this._disableRipple = coerceBooleanProperty(value); }
3032

3133
constructor(...args: any[]) { super(...args); }
32-
}
33-
34-
// Since we don't directly extend from `base` with it's original types, and we instruct
35-
// TypeScript that `T` actually is instantiatable through `new`, the types don't overlap.
36-
// This is a limitation in TS as abstract classes cannot be typed properly dynamically.
37-
return Mixin as unknown as T & CanDisableRippleCtor;
34+
};
3835
}

src/material/core/common-behaviors/disabled.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {coerceBooleanProperty} from '@angular/cdk/coercion';
10-
import {Constructor} from './constructor';
10+
import {AbstractConstructor, Constructor} from './constructor';
1111

1212
/** @docs-private */
1313
export interface CanDisable {
@@ -16,9 +16,10 @@ export interface CanDisable {
1616
}
1717

1818
/** @docs-private */
19-
export type CanDisableCtor = Constructor<CanDisable>;
19+
export type CanDisableCtor = Constructor<CanDisable> & AbstractConstructor<CanDisable>;
2020

2121
/** Mixin to augment a directive with a `disabled` property. */
22+
export function mixinDisabled<T extends AbstractConstructor<{}>>(base: T): CanDisableCtor & T;
2223
export function mixinDisabled<T extends Constructor<{}>>(base: T): CanDisableCtor & T {
2324
return class extends base {
2425
private _disabled: boolean = false;

src/material/core/common-behaviors/error-state.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import {FormControl, FormGroupDirective, NgControl, NgForm} from '@angular/forms';
1010
import {Subject} from 'rxjs';
1111
import {ErrorStateMatcher} from '../error/error-options';
12-
import {Constructor} from './constructor';
12+
import {AbstractConstructor, Constructor} from './constructor';
1313

1414

1515
/** @docs-private */
@@ -21,7 +21,8 @@ export interface CanUpdateErrorState {
2121
}
2222

2323
/** @docs-private */
24-
export type CanUpdateErrorStateCtor = Constructor<CanUpdateErrorState>;
24+
export type CanUpdateErrorStateCtor = Constructor<CanUpdateErrorState> &
25+
AbstractConstructor<CanUpdateErrorState>;
2526

2627
/** @docs-private */
2728
export interface HasErrorState {
@@ -35,8 +36,10 @@ export interface HasErrorState {
3536
* Mixin to augment a directive with updateErrorState method.
3637
* For component with `errorState` and need to update `errorState`.
3738
*/
38-
export function mixinErrorState<T extends Constructor<HasErrorState>>(base: T)
39-
: CanUpdateErrorStateCtor & T {
39+
export function mixinErrorState<T extends AbstractConstructor<HasErrorState>>(base: T):
40+
CanUpdateErrorStateCtor & T;
41+
export function mixinErrorState<T extends Constructor<HasErrorState>>(base: T):
42+
CanUpdateErrorStateCtor & T {
4043
return class extends base {
4144
/** Whether the component is in an error state. */
4245
errorState: boolean = false;

src/material/core/common-behaviors/tabindex.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ export interface HasTabIndex {
2121
}
2222

2323
/** @docs-private */
24-
export type HasTabIndexCtor = Constructor<HasTabIndex>;
24+
export type HasTabIndexCtor = Constructor<HasTabIndex> & AbstractConstructor<HasTabIndex>;
2525

2626
/** Mixin to augment a directive with a `tabIndex` property. */
27-
export function mixinTabIndex<T extends AbstractConstructor<CanDisable>>(
27+
export function mixinTabIndex<T extends AbstractConstructor<CanDisable>>(base: T,
28+
defaultTabIndex?: number): HasTabIndexCtor & T;
29+
export function mixinTabIndex<T extends Constructor<CanDisable>>(
2830
base: T, defaultTabIndex = 0): HasTabIndexCtor & T {
29-
// Note: We cast `base` to `unknown` and then `Constructor`. It could be an abstract class,
30-
// but given we `extend` it from another class, we can assume a constructor being accessible.
31-
abstract class Mixin extends (base as unknown as Constructor<CanDisable>) {
31+
return class extends base implements HasTabIndex {
3232
private _tabIndex: number = defaultTabIndex;
3333
defaultTabIndex = defaultTabIndex;
3434

@@ -41,10 +41,5 @@ export function mixinTabIndex<T extends AbstractConstructor<CanDisable>>(
4141
constructor(...args: any[]) {
4242
super(...args);
4343
}
44-
}
45-
46-
// Since we don't directly extend from `base` with it's original types, and we instruct
47-
// TypeScript that `T` actually is instantiatable through `new`, the types don't overlap.
48-
// This is a limitation in TS as abstract classes cannot be typed properly dynamically.
49-
return Mixin as unknown as T & Constructor<HasTabIndex>;
44+
};
5045
}

tools/public_api_guard/material/core.d.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,19 @@ export interface CanColor {
6262
defaultColor: ThemePalette | undefined;
6363
}
6464

65-
export declare type CanColorCtor = Constructor<CanColor>;
65+
export declare type CanColorCtor = Constructor<CanColor> & AbstractConstructor<CanColor>;
6666

6767
export interface CanDisable {
6868
disabled: boolean;
6969
}
7070

71-
export declare type CanDisableCtor = Constructor<CanDisable>;
71+
export declare type CanDisableCtor = Constructor<CanDisable> & AbstractConstructor<CanDisable>;
7272

7373
export interface CanDisableRipple {
7474
disableRipple: boolean;
7575
}
7676

77-
export declare type CanDisableRippleCtor = Constructor<CanDisableRipple>;
77+
export declare type CanDisableRippleCtor = Constructor<CanDisableRipple> & AbstractConstructor<CanDisableRipple>;
7878

7979
export interface CanUpdateErrorState {
8080
errorState: boolean;
@@ -83,7 +83,7 @@ export interface CanUpdateErrorState {
8383
updateErrorState(): void;
8484
}
8585

86-
export declare type CanUpdateErrorStateCtor = Constructor<CanUpdateErrorState>;
86+
export declare type CanUpdateErrorStateCtor = Constructor<CanUpdateErrorState> & AbstractConstructor<CanUpdateErrorState>;
8787

8888
export declare abstract class DateAdapter<D> {
8989
protected readonly _localeChanges: Subject<void>;
@@ -148,7 +148,7 @@ export interface HasTabIndex {
148148
tabIndex: number;
149149
}
150150

151-
export declare type HasTabIndexCtor = Constructor<HasTabIndex>;
151+
export declare type HasTabIndexCtor = Constructor<HasTabIndex> & AbstractConstructor<HasTabIndex>;
152152

153153
export declare const MAT_DATE_FORMATS: InjectionToken<MatDateFormats>;
154154

@@ -280,13 +280,13 @@ export declare class MatRippleModule {
280280
static ɵmod: i0.ɵɵNgModuleDeclaration<MatRippleModule, [typeof i1.MatRipple], [typeof i2.MatCommonModule, typeof i3.PlatformModule], [typeof i1.MatRipple, typeof i2.MatCommonModule]>;
281281
}
282282

283-
export declare function mixinColor<T extends Constructor<HasElementRef>>(base: T, defaultColor?: ThemePalette): CanColorCtor & T;
283+
export declare function mixinColor<T extends AbstractConstructor<HasElementRef>>(base: T, defaultColor?: ThemePalette): CanColorCtor & T;
284284

285-
export declare function mixinDisabled<T extends Constructor<{}>>(base: T): CanDisableCtor & T;
285+
export declare function mixinDisabled<T extends AbstractConstructor<{}>>(base: T): CanDisableCtor & T;
286286

287287
export declare function mixinDisableRipple<T extends AbstractConstructor<{}>>(base: T): CanDisableRippleCtor & T;
288288

289-
export declare function mixinErrorState<T extends Constructor<HasErrorState>>(base: T): CanUpdateErrorStateCtor & T;
289+
export declare function mixinErrorState<T extends AbstractConstructor<HasErrorState>>(base: T): CanUpdateErrorStateCtor & T;
290290

291291
export declare function mixinInitialized<T extends Constructor<{}>>(base: T): HasInitializedCtor & T;
292292

0 commit comments

Comments
 (0)