从存储库中获取模型,而无需通过尖括号指定类型

Get model from repository without having to specify type through angle brackets

我想创建一个包含许多不同模型的存储库。从存储库中获取其中一个模型时,我希望打字稿知道模型的类型,而不必手动指定它是哪种类型。

export class Repository {
    items = {};

    add<T>(name: string, item: T) {
        this.items[name] = item;
    }

    get(name: string) {
        return this.items[name];
    }
}

class BaseModel {
    insert() {}
}

class ImageModel extends BaseModel {
    displayImage() {}
}

class UserModel extends BaseModel {
    doSomething() {}
}

class DataService {
    repository: Repository = new Repository();
}

const service = new DataService();
service.repository.add<ImageModel>('image', new ImageModel());
service.repository.add<UserModel>('user', new UserModel());

const imageModel = <ImageModel>service.repository.get('image');
const userModel = <UserModel>service.repository.get('user');

imageModel.displayImage();
userModel.doSomething();


现在,当从存储库中获取模型时,我说例如变量 imageModel 将是 ImageModel 类型,而 userModel 将是 UserModel 类型。有没有办法让编译器知道它分别是 ImageModel 和 UserModel 类型,而不必在从存储库获取它时指定它?可以通过使用泛型和/或 infer 关键字吗?

假设在您的存储库中,每种类型的模型只有一个实例,那么简化代码的一种可能方法是使用 Map 并使用构造函数作为键。从下面的示例中可以看出,这可以使您的代码更简单、更清晰。

class Repository {
    items: Map<Function, BaseModel> = new Map();

    add<T extends BaseModel>(item: T) {
        this.items.set(item.constructor, item);
    }

    get<T extends BaseModel>(type: new () => T) {
        return this.items.get(type)! as T;
    }
}

class BaseModel {
    insert() { }
}

class ImageModel extends BaseModel {
    displayImage() { }
}

class UserModel extends BaseModel {
    doSomething() { }
}

class DataService {
    repository: Repository = new Repository();
}

const service = new DataService();
service.repository.add(new ImageModel()); // Now you don't need to specify anything here
service.repository.add(new UserModel());

const imageModel = service.repository.get(ImageModel); // As simple as it can possibly be
const userModel = service.repository.get(UserModel);

imageModel.displayImage(); // It works! TypeScript knows imageModel is an ImageModel
userModel.doSomething();

如果你必须使用字符串作为键来识别模型,并且键可能会改变,那么我必须同意 Aluan Haddad 的观点,你想要的是不可能的。 TypeScript 无法知道哪个键引用哪个类型,除非相关性是固定的并且您在代码中的某处定义了相关性。