#javascript #typescript #single-page-application
#javascript #typescript #одностраничное приложение
Вопрос:
Приложение, над которым я работаю, имеет несколько products
. Конфигурация, зависящая от продукта, поможет избежать if-else
. Кроме того, я хочу убедиться, что ключи конфигурации поддерживаются в конфигурации для конкретного продукта. Это достигается за счет использования interface
, чтобы разработчик не пропустил key
при добавлении его в продукт.
То, что я ищу, — это некоторые предложения по следующим пунктам —
- Хотя этот объект может увеличиться и стать большим по размеру, я также хочу убедиться, что этот класс будет
dynamically
импортировать объект на основе currentproduct-name
(product1 | product2
) и т. Д. (Так что общая производительность может быть улучшена.) - Лучший способ написать
ProductConfigService
класс, если таковой имеется. - ИЛИ другой подход, который можно сделать эффективно (используя TS)
Пожалуйста, предложите.
interface PRODUCT_CONFIG {
API_KEY: string,
AGE: number,
TEXT: string
}
const product1: PRODUCT_CONFIG = {
API_KEY: "SOME_VALUE",
AGE: 10,
TEXT: "SOME_VALUE"
}
const product2: PRODUCT_CONFIG = {
API_KEY: "SOME_VALUE"
AGE: 12,
TEXT: "SOME_VALUE"
}
class ProductConfigService {
private product: PRODUCT_CONFIG;
constructor(private accessKey:string) {
this.product = product2; // should be dynamic based on the current selected application. This is hard-coded to product2.
}
getConfig(): string {
//@ts-ignore
return this.product[this.accessKey];
}
}
// consumer.
let product = new ProductConfigService('AGE');
console.log(product.getConfig());
Комментарии:
1. Почему он
product2
хранится вthis.product
, а неproduct1
в другом объекте? Вы ищете непустоеAGE
свойство из-заProductConfigService('AGE')
?2. мой плохой. По сути, продукт назначается динамически. Объект содержит соответствующую информацию, если это применимо к продукту, если нет, он будет пустым. Но, тем не менее, ключ существует в виде общего кода.
Ответ №1:
Я бы создал абстрактный класс, который будет наследоваться в соответствии с потребностями каждого приложения.
По умолчанию было бы PRODUCT_CONFIG
значение по умолчанию, которое также можно было бы расширить.
В следующем коде getConfig()
возвращает правильный тип значения в зависимости от настроенного ключа.
предупреждение: раздражает то, что пользователь ProductConfigService
должен указать имя key
, используемое для конфигурации. Я не знаю, как извлечь его из самого параметра.
// ---------- ABSTRACT CLASS DECLARATION
interface PRODUCT_CONFIG {
API_KEY: string;
AGE: number;
TEXT: string;
}
abstract class AProductConfigService<T extends PRODUCT_CONFIG, U extends keyof T> {
protected product: T;
protected accessKey: keyof T;
constructor(accessKey: keyof T, product: T) {
this.accessKey = accessKey
this.product = product;
}
public getConfig(): T[U] {
return this.product[this.accessKey] as T[U];
}
}
// ---------- CLASS IMPLEMENTATION
interface EXTENDED_PRODUCT_CONFIG extends PRODUCT_CONFIG {
// additionnal keys ...
ANIMAL: string;
}
class ProductConfigService<U extends keyof EXTENDED_PRODUCT_CONFIG> extends AProductConfigService<EXTENDED_PRODUCT_CONFIG, U> {
constructor(accessKey: U) {
super(accessKey, product2);
}
// ... new methods
}
// ---------- PRODUCTS DEFINITION
const product1: PRODUCT_CONFIG = {
API_KEY: 'SOME_VALUE',
AGE: 10,
TEXT: 'SOME_VALUE',
}
const product2: EXTENDED_PRODUCT_CONFIG = {
API_KEY: 'SOME_VALUE',
AGE: 12,
TEXT: 'SOME_VALUE',
ANIMAL: 'fox',
}
// -------------- PRODUCT USE
const productA = new ProductConfigService<'AGE'>('AGE');
const valA = productA.getConfig();
console.log(valA);
const productB = new ProductConfigService<'API_KEY'>('API_KEY');
const valB = productB.getConfig();
console.log(valB);
const productC = new ProductConfigService<'ANIMAL'>('ANIMAL');
const valC = productC.getConfig();
console.log(valC);
// ----------------