基于TypeScript 2.8与Immutable 4.0 RC.9的通用模型函数实现问询
Got it, let's work through this. You want to create model classes with shared properties, then write a generic function that can handle any instance of these models—all while using Immutable.js and TypeScript 2.8. Here's a clean, scalable approach:
Step 1: Define Shared Properties & Base Model
First, let's lock down the common properties all your models will share, then create a base Immutable Record class that encapsulates these. This ensures every model inherits the shared props and any common methods you want.
import { Set, Record } from 'immutable'; // Interface defining all shared properties across models interface CommonModelProps { id: string; createdAt: Date; lastUpdated: Date; } // Abstract base class extending Immutable Record for shared behavior abstract class BaseModel<T extends CommonModelProps> extends Record<T> { // Shared method to get the model's ID public getEntityId(): string { return this.get('id'); } // Shared method to check if the model was recently updated (within 24h) public isRecentlyUpdated(): boolean { const dayInMs = 24 * 60 * 60 * 1000; return Date.now() - this.get('lastUpdated').getTime() < dayInMs; } }
Step 2: Create Specific Model Classes
Now build your actual model classes by extending the base, adding their unique properties:
// Animal-specific properties interface AnimalProps extends CommonModelProps { species: string; isDomesticated: boolean; } class Animal extends BaseModel<AnimalProps> { // Animal-specific method public getSpecies(): string { return this.get('species'); } } // Beast-specific properties interface BeastProps extends CommonModelProps { habitat: string; threatLevel: number; } class Beast extends BaseModel<BeastProps> { // Beast-specific method public isHighThreat(): boolean { return this.get('threatLevel') >= 8; } }
Step 3: The Generic Function for Shared Properties
Now write your generic function. We'll use a type constraint to ensure the input is always a BaseModel (so it has all the shared properties/methods):
// Generic function that works with ANY BaseModel instance function processSharedModelProps<T extends CommonModelProps>(model: BaseModel<T>): void { console.log(`Processing model with ID: ${model.getEntityId()}`); console.log(`Created at: ${model.get('createdAt').toLocaleString()}`); if (model.isRecentlyUpdated()) { console.log("⚠️ This model was updated in the last 24 hours"); } // Add any other shared property logic here! }
Step 4: Using the Function with Your Models
Testing this is straightforward—pass any model instance, and the function handles it seamlessly:
// Create sample instances const myCat = new Animal({ id: 'animal_001', createdAt: new Date('2024-01-15'), lastUpdated: new Date(), species: 'Felis catus', isDomesticated: true }); const myWolf = new Beast({ id: 'beast_001', createdAt: new Date('2023-10-05'), lastUpdated: new Date('2024-02-20'), habitat: 'Forest', threatLevel: 7 }); // Process both with the same generic function processSharedModelProps(myCat); processSharedModelProps(myWolf);
Bonus: Handling Your Factory Classes
Since you started with Factory subclasses, here's how to extend this to handle static shared properties (like your x: Set<{id: string}>):
// Base factory with shared static property and methods abstract class BaseFactory<M extends BaseModel<any>> { public static models: Set<M> = Set([]); // Shared static method to add a model to the set public static addModel(model: M): void { this.models = this.models.add(model); } } // Animal Factory extending the base class AnimalFactory extends BaseFactory<Animal> { // Animal-specific factory method public static createAnimal(props: AnimalProps): Animal { const animal = new Animal(props); this.addModel(animal); return animal; } } // Beast Factory extending the base class BeastFactory extends BaseFactory<Beast> { // Beast-specific factory method public static createBeast(props: BeastProps): Beast { const beast = new Beast(props); this.addModel(beast); return beast; } } // Generic function to log all models in any factory function logFactoryModels<F extends typeof BaseFactory>(factory: F): void { console.log(`\n${factory.name} has ${factory.models.size} models:`); factory.models.forEach(model => { console.log(`- ID: ${model.getEntityId()}`); }); } // Use the factories AnimalFactory.createAnimal(myCat.toObject() as AnimalProps); BeastFactory.createBeast(myWolf.toObject() as BeastProps); // Log all models from both factories logFactoryModels(AnimalFactory); logFactoryModels(BeastFactory);
This setup keeps your code DRY, enforces type safety (thanks to TypeScript 2.8's generic constraints), and plays nicely with Immutable.js's Record system.
内容的提问来源于stack exchange,提问作者Stefan

