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

时间:2019-06-19 17:35:38

标签: typescript typescript-generics

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

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关键字吗?

1 个答案:

答案 0 :(得分:0)

假设在您的存储库中,每种类型的模型都只有一个实例,那么简化代码的一种可能方法是使用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不可能知道哪个键指向哪种类型。