Skip to content

Instantly share code, notes, and snippets.

@devversion
Created August 21, 2020 07:58
Show Gist options
  • Save devversion/eec8ff59effba2ec83d8d197602081be to your computer and use it in GitHub Desktop.
Save devversion/eec8ff59effba2ec83d8d197602081be to your computer and use it in GitHub Desktop.
diff --git a/src/material/core/common-behaviors/tabindex.ts b/src/material/core/common-behaviors/tabindex.ts
index b5788d46c..3be2d0193 100644
--- a/src/material/core/common-behaviors/tabindex.ts
+++ b/src/material/core/common-behaviors/tabindex.ts
@@ -23,10 +23,15 @@ export interface HasTabIndex {
/** @docs-private */
export type HasTabIndexCtor = Constructor<HasTabIndex>;
+// Needs JSDOC
+type LooseConstructor<T> = Function & { prototype: T };
+
/** Mixin to augment a directive with a `tabIndex` property. */
-export function mixinTabIndex<T extends Constructor<CanDisable>>(base: T, defaultTabIndex = 0)
- : HasTabIndexCtor & T {
- return class extends base {
+export function mixinTabIndex<T extends LooseConstructor<CanDisable>>(
+ base: T, defaultTabIndex = 0): HasTabIndexCtor & T {
+ // Note: We cast `base` to `unknown` and then `Constructor`. It could be an abstract class,
+ // but given we `extend` it from another class, we can assume a constructor being accessible.
+ abstract class Mixin extends (base as unknown as Constructor<CanDisable>) {
private _tabIndex: number = defaultTabIndex;
defaultTabIndex = defaultTabIndex;
@@ -39,5 +44,10 @@ export function mixinTabIndex<T extends Constructor<CanDisable>>(base: T, defaul
constructor(...args: any[]) {
super(...args);
}
- };
+ }
+
+ // Since we don't directly extend from `base` with it's original types, and we instruct
+ // TypeScript that `T` actually is instantiatable through `new`, the types don't overlap.
+ // This is a limitation in TS as abstract classes cannot be typed properly dynamically.
+ return Mixin as unknown as T & Constructor<HasTabIndex>;
}
diff --git a/src/material/radio/radio.ts b/src/material/radio/radio.ts
index c54097c17..fee3d61f9 100644
--- a/src/material/radio/radio.ts
+++ b/src/material/radio/radio.ts
@@ -334,11 +334,11 @@ export class MatRadioGroup extends _MatRadioGroupBase<MatRadioButton> {
// Boilerplate for applying mixins to MatRadioButton.
/** @docs-private */
-class MatRadioButtonBase {
+abstract class MatRadioButtonBase {
// Since the disabled property is manually defined for the MatRadioButton and isn't set up in
// the mixin base class. To be able to use the tabindex mixin, a disabled property must be
// defined to properly work.
- disabled: boolean;
+ abstract disabled: boolean;
constructor(public _elementRef: ElementRef) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment