Constrained Mixins की जानकारी
In this page:
function MixinName<TBase extends Constructor<Required>>(Base: TBase) {
return class extends Base {
// can use members of Required
};
}
Why Constrain a Mixin?
एक mixin को कभी-कभी कुछ उपयोगी जोड़ने से पहले base class पर पहले से मौजूद एक specific property या method चाहिए होता है — एक structural constraint उस requirement को explicit और TypeScript से checkable बना देता है।
उदाहरण: Why Constrain a Mixin?
interface HasName { name: string; }
type Constructor<T = {}> = new (...args: any[]) => T;
function Greetable<TBase extends Constructor<HasName>>(Base: TBase) {
return class extends Base {
greet() { return `Hello, ${this.name}`; }
};
}
class Person { name = "Ravi"; }
class GreetablePerson extends Greetable(Person) {}
console.log(new GreetablePerson().greet());
Constraining with Interfaces
एक interface exactly describe कर सकता है कि base class के पास पहले से कौन सी capability होनी चाहिए; mixin का constructor-type parameter फिर उस requirement enforce करने के लिए उस interface को एक construct signature के साथ combine करता है।
उदाहरण: Constraining with Interfaces
interface Timestamped { createdAt: Date; }
type Constructor<T = {}> = new (...args: any[]) => T;
function Auditable<TBase extends Constructor<Timestamped>>(Base: TBase) {
return class extends Base {
age() { return Date.now() - this.createdAt.getTime(); }
};
}
class Record_ { createdAt = new Date(); }
class AuditableRecord extends Auditable(Record_) {}
console.log(typeof new AuditableRecord().age());
Constrained Method Requirements
एक mixin एक field के बजाय एक specific method require कर सकता है — constraint यह सुनिश्चित करता है कि base class actually एक callable member expose करे जो mixin internally depend करने वाले signature से match करे।
उदाहरण: Constrained Method Requirements
interface Serializable { serialize(): string; }
type Constructor<T = {}> = new (...args: any[]) => T;
function Loggable<TBase extends Constructor<Serializable>>(Base: TBase) {
return class extends Base {
log() { console.log(this.serialize()); }
};
}
class Data {
serialize() { return "data payload"; }
}
class LoggableData extends Loggable(Data) {}
new LoggableData().log();
Multiple Constraints
जब एक mixin एक साथ कई capabilities पर depend करता है, उन्हें एक single interface में combine करें — pass किया गया base class उस combined interface के हर member को satisfy करना चाहिए, सिर्फ कुछ को नहीं।
उदाहरण: Multiple Constraints
interface HasName { name: string; }
interface HasAge { age: number; }
type Constructor<T = {}> = new (...args: any[]) => T;
function Describable<TBase extends Constructor<HasName & HasAge>>(Base: TBase) {
return class extends Base {
describe() { return `${this.name}, age ${this.age}`; }
};
}
class Person { name = "Ravi"; age = 25; }
class DescribablePerson extends Describable(Person) {}
console.log(new DescribablePerson().describe());
Benefits of Constrained Mixins
Constraints reliability improve करते हैं क्योंकि एक incompatible base class runtime पर mysteriously fail होने के बजाय compile time पर reject हो जाती है, और वे यह documentation भी देते हैं कि mixin अपने input से exactly क्या expect करता है।
उदाहरण: Benefits of Constrained Mixins
interface HasId { id: number; }
type Constructor<T = {}> = new (...args: any[]) => T;
function Findable<TBase extends Constructor<HasId>>(Base: TBase) {
return class extends Base {
key() { return `record-${this.id}`; }
};
}
class Entity { id = 1; }
class FindableEntity extends Findable(Entity) {}
console.log(new FindableEntity().key());
- एक mixin को एक ऐसी base class पर उपयोग करना जिसमें required property न हो, जैसे
name, जो compile fail होता है। - सिर्फ
Constructorसे constrain करना और फिर mixin के अंदरthis.nameउपयोग करना, जो एक error है। TBase extends HasNameलिखना बजायTBase extends Constructor<HasName>के, क्योंकि constraint को एक class describe करना चाहिए, एक instance नहीं।
Chapter Quiz — Complete all 4 topics to unlock
0/4 topics done
Complete these topics first: