如何在Angular项目中重写Material库的readonly属性getter?
shouldPlaceholderFloat in MatChipList & Best Practices for Modifying External TypeScript Classes Hey there! Let's break down how to fix that bug in MatChipList and cover the best ways to tweak external classes in TypeScript when you're working with Angular.
Quick Fix for the shouldPlaceholderFloat Bug
Since you're dealing with a specific readonly getter bug in Material 2.0.0-beta.12, the fastest way to apply your fix without waiting for an official patch is using monkey patching (modifying the class prototype). Here's how to do it:
Add this code to your
main.tsfile (or in anAPP_INITIALIZERprovider if you prefer running it after Angular bootstraps):import { MatChipList } from '@angular/material/chips'; // Override the faulty getter with the correct implementation // @ts-ignore (to bypass TypeScript's readonly property error) Object.defineProperty(MatChipList.prototype, 'shouldPlaceholderFloat', { get: function() { return !this.empty; }, configurable: true, enumerable: true });This will globally replace the getter for all instances of
MatChipListin your app—no need to change any of your template or component code that uses<mat-chip-list>.If you want to keep TypeScript type-checking happy (instead of using
// @ts-ignore), you can extend the type definition ofMatChipList:declare module '@angular/material/chips' { interface MatChipList { // Re-declare the property to allow redefining the getter shouldPlaceholderFloat: boolean; } }Add this declaration in a
.d.tsfile (likematerial-overrides.d.ts) that's included in your TypeScript compilation path.
Best Practices for Modifying External TypeScript Classes
When you need to tweak properties or methods from libraries you don't own, here are the most common approaches, each with pros and cons:
1. Monkey Patching (Prototype Modification)
- Use case: Quick, temporary fixes (like your current scenario where you're waiting for an official patch).
- Pros: No need to rewrite existing code that uses the original class; immediate global effect.
- Cons: Type-unsafe by default; can cause conflicts if other code modifies the same prototype; may break when the library is updated.
2. Inheritance (Extend the Class)
- Use case: Long-term modifications where you want to maintain type safety and OOP principles.
- How to do it: Create a subclass that overrides the faulty property/method:
import { MatChipList } from '@angular/material/chips'; import { Component } from '@angular/core'; @Component({ selector: 'custom-mat-chip-list', // Use this selector instead of <mat-chip-list> template: '<ng-content></ng-content>', // Make sure to inherit all the original MatChipList providers/styles if needed providers: [...MatChipList.providers] }) export class CustomMatChipList extends MatChipList { get shouldPlaceholderFloat(): boolean { return !this.empty; } } - Pros: Type-safe; clean OOP approach; easy to maintain.
- Cons: Requires replacing all instances of
<mat-chip-list>with your custom selector; may need to handle inherited providers/styles.
3. Wrapper/Decorator Pattern
- Use case: When you need to add extra logic around the original class, not just override a single property.
- How to do it: Create a component that wraps the original
MatChipList, usesViewChildto access its instance, and overrides behavior where needed. - Pros: Isolates your changes from the original class; flexible for adding new features.
- Cons: More boilerplate code; may not be ideal for simple getter overrides.
Final Notes
- Remember to remove your monkey patch or custom subclass once you upgrade to a Material version where the
shouldPlaceholderFloatbug is fixed! - Always test thoroughly after applying any of these changes, especially when upgrading the library.
内容的提问来源于stack exchange,提问作者Marcin Kapusta

