Получить модель из хранилища без указания типа через угловые скобки - PullRequest
1 голос
/ 19 июня 2019

Я хочу создать репозиторий, содержащий много разных моделей.Когда я получаю одну из моделей из репозитория, я хочу, чтобы машинопись набирала тип модели без необходимости вручную указывать, какой это тип.

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();


Прямо сейчас, при получении модели из репозитория Iскажем, например, что переменная imageModel будет иметь тип ImageModel, а userModel будет иметь тип UserModel.Есть ли способ, чтобы компилятор знал, что он имеет тип ImageModel и UserModel соответственно, без необходимости указывать его при получении из хранилища?Можно ли использовать дженерики и / или ключевое слово infer?

1 Ответ

0 голосов
/ 23 июня 2019

Если предположить, что в вашем репозитории каждый тип модели будет иметь только один экземпляр, то одним из возможных способов упростить ваш код будет использование 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();

Если вы должны использовать строки в качестве ключей для идентификации моделей, и ключи могут измениться, тогда я должен согласиться с Алуаном Хаддадом, что то, что вы хотите, невозможно. TypeScript не может знать, какой ключ относится к какому типу, если только корреляция не установлена ​​и вы не определите корреляцию где-нибудь в своем коде.

...