Одноэлементный класс в javascript с условным параметром

#javascript #reactjs #typescript #oop #singleton

#javascript #reactjs #typescript #ооп #одноэлементный

Вопрос:

У меня есть два класса :

useService.ts

 import { useMemo } from 'react';

/**
 * Hook will take the singletone service instance later keeping it memoized
 * @param service
 */
export function useService<T> ( service: { new (): T; getInstance (): T } ): T {
    return useMemo<T>(() => service.getInstance(), []);
}

/**
 * Hook will take instance of the given class memoized
 * @param Class
 * @param args
 */
export function useClass<S, A extends []> ( Class: { new ( ...args: A ): S }, ...args: A ): S {
    return useMemo<S>(() => new Class(...args), []);
}
 

CartService.ts

 var CART_ITEMS_KEY = 'SOME_KEY';

export class CartService {
private static __SELF__: CartService;
private __items: CartItem[] = [];
private auth: AuthService;
private api: APIService;
private endpoint: AxiosInstance;

constructor (cartItemsKey) {
    CART_ITEMS_KEY = cartItemsKey;
    this.auth = AuthService.getInstance();
    this.api = APIService.getInstance();
    this.endpoint = this.api.createEndpoint('cart');

    this.init();
}

/**
 * Get singletone service instance
 */
public static getInstance (): CartService {
    if ( !CartService.__SELF__ ) {
        CartService.__SELF__ = new CartService();
    }

    return CartService.__SELF__;
}
}
 

Я хочу инициализировать объект CartService и передать его в UserService следующим образом.

useService(CartService(«SOME_NEW_KEY»))

Я пробовал много подходов, но получал ошибки.

Комментарии:

1. userService здесь не определено. Вы имеете в виду useService ?

2. Вы хотите инициализировать без ключевого слова new? попробуйте, если нет ограничений с новым ключевым словом UserService(new CartService(«SOME_NEW_KEY»)) или

3. @RajaJaganathan Да, я хочу внедрить его без нового ключевого слова.

4. @gqstav Да, это опечатка. Его useService

Ответ №1:

userService(CartService("SOME_NEW_KEY")) Это недопустимый синтаксис в typescript, вы можете получить ошибку типа Value of type 'typeof CartService' is not callable.

При создании экземпляра CartService нам нужно передать cartItemsKey конструктору.

   /**
   * Get singleton service instance
   */
  public static getInstance(cartItemsKey): CartService {
    if (!CartService.__SELF__) {
      CartService.__SELF__ = new CartService(cartItemsKey);
    }

    return CartService.__SELF__;
  }
 

Вызовите, как показано ниже

 userService(CartService.getInstance("SOME_NEW_KEY"))
 

Комментарии:

1. Аргумент типа ‘CartService’ не может быть присвоен параметру типа ‘{new (): неизвестно; getInstance(): неизвестно; }’. Свойство ‘getInstance’ отсутствует в типе ‘CartService’, но требуется в типе ‘{new (): неизвестно; getInstance(): неизвестно; }’. Получение этой ошибки

2. Воспроизводимая ошибка была бы полезна здесь, stackblitz.com/edit/typescript-playground-ea1fbj?file=index.ts . Обратите внимание, что я не видел здесь никаких проблем

3. Вам не хватает еще одного класса. useService я должен передать объект в нем.

4. stackblitz.com/edit/typescript-playground-zceawm?file=index.ts

5. попробуйте так stackblitz.com/edit/typescript-playground-yj8a2t?file=index.ts

Ответ №2:

Попробуйте это:

useService.ts

 import { useMemo } from 'react';

/**
 * Hook will take the singleton service instance later keeping it memoized
 * @param service
 */
export function useService<T>(
  service: {
    new (): T;
    getInstance(...args: String[]): T;
  },
  args: String[]
): T {
  return useMemo<T>(() => service.getInstance(...args), []);
}

/**
 * Hook will take instance of the given class memoized
 * @param Class
 * @param args
 */
export function useClass<S, A extends []>(
  Class: { new (...args: A): S },
  ...args: A
): S {
  return useMemo<S>(() => new Class(...args), []);
}
 

CartService.ts

 export class CartService {
  private static __SELF__: CartService;
  private cartItemsKey: String;
  private cartId: String;

  constructor(cartItemsKey: String = 'default', cartId: String = 'default') {
    this.cartItemsKey = cartItemsKey;
    this.cartId = cartId;
  }

  log() {
    console.log('cartId: '   this.cartId);
    console.log('cartItemsKey: '   this.cartItemsKey);
  }

  /**
   * Get singletone service instance
   */
  public static getInstance(...args: String[]): CartService {
    if (!CartService.__SELF__) {
      CartService.__SELF__ = new CartService(...args);
    }

    return CartService.__SELF__;
  }
}
 

А затем используйте его следующим образом:

 let cartService = useService(CartService, [
    'SOME_KEY_FROM_TEST',
    'SOME_ID_FROM_TEST'
  ]);
cartService.log()