javascript - 如何使此类在 typescript 中可重用?元编程?子类?注入(inject)模块?

标签 javascript typescript metaprogramming typescript2.0

我有这个EventsStorage typescript 类,它负责在ionic-storage(sqlite和indexedDB的包装器)中存储和检索Event对象。它自始至终都使用我的 Event 类。

我想将很多这样的逻辑重用于事件以外的其他东西,比如小部件。

我有 Ruby 背景,提取所有存储逻辑、设置一个实际上是类 Event 的 ruby​​ var 并在任何使用 Event 的地方使用该 var 会相对简单。我可以在 typescript 中做类似的事情吗?是否有另一种机制可以让我将此类的大部分内容重用于其他内容,例如 Widget?

理想情况下,我的 EventsStorage 类变得非常轻量级,而且我不仅仅是包装对 this.some_storage_module.get_ids()this.some_storage_module.insert_new_objs() 的调用-- 必须将其复制/粘贴到我需要的每个其他实例。

类似这样的事情:

export class EventsStorage {  // extends BaseStorage (maybe??)
  constructor(){
    super(Event, 'events'); // or some small set of magical args
  }
}

这是现有的类:

import { Injectable } from '@angular/core';
import { Storage }    from '@ionic/storage';

import { Event }      from '../classes/event';

// EventsStorage < EntityStorage
// - tracks local storage info
// - a key to an array of saved objects
// - a query() method that returns saved objects

@Injectable()
export class EventsStorage {
  base_key: string;
  ids_key: string;

  constructor(
    private storage: Storage
  ){
    this.base_key = 'event';
    this.ids_key = [this.base_key, 'ids'].join('_');
  }

  get_ids(): Promise<any>{
    return this.storage.ready().then(() => {
      return this.storage.get(this.ids_key).then((val) => {
        if(val === null){
          return [];
        } else {
          return val;
        }
      });
    });
  }

  insert_new_objs(new_objs: any): Promise<any>{
    return new_objs.reduce((prev: Promise<string>, cur: any): Promise<any> => {
      return prev.then(() => {
        return this.storage.set(cur._id, cur.event);
      });
    }, Promise.resolve()).then(() => {
      console.log('saving event_ids');
      return this.storage.set(this.ids_key, new_objs.map(obj => obj._id));
    });
  }

  update(events: Event[]): Promise<any> {
    let new_objs = events.map((event) => {
      return {
        _id: [this.base_key, event.id].join('_'),
        event: event
      };
    });

    return this.insert_new_objs(new_objs);
  }

  query(): Promise<Event[]>{
    let events = [];
    return this.get_ids().then((ids) => {
      return ids.reduce((prev: Promise<string>, cur: string): Promise<any> => {
        return prev.then(() => {
          return this.get_id(cur).then((raw_event) => {
            events = events.concat([raw_event as Event]);
            return events;
          });
        });
      }, Promise.resolve());
    });
  }

  get_id(id: string): Promise<Event>{
    return this.storage.get(id).then((raw_event) => {
      return raw_event;
    });
  }
}

最佳答案

在我看来你想使用泛型。您基本上在要存储的所有内容之间定义了一些基本接口(interface),并且您的代码应该依赖于该接口(interface)。据我所知,在您的代码中仅使用 id 属性。

所以它看起来有点像这样

import { Event }  from '...';
import { Widget } from '...';
interface HasId{
    id: string;
}

class ItemsStorage<T extends HasId> {
 ....
 get_id(id: string): Promise<T>{
    ...
 }
}

const EventStorage = new ItemsStorage<Events>(storage);
const WidgetStorage = new ItemsStorage<Widget>(storage);
const ev = EventStorage.get_id('abc');     //type is Promise<Event>
const wd = WidgetStorage.get_id('def');    //type is Promise<Widget>

您可以阅读有关泛型的更多信息 here .

编辑: 1 - 关于子类化 - 通常不太可取。如果您的 ItemsStorage 类在处理事件与小部件时需要不同的行为,那么子类化就是您的解决方案。但是,如果每个类都有相同的行为,人们可能会称您的代码为泛型,并且使用泛型会更好。

关于javascript - 如何使此类在 typescript 中可重用?元编程?子类?注入(inject)模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42013379/

相关文章:

javascript - IE8 中未定义的 JQuery

javascript - 我可以直接从 React 中的 JSX/TSX 调用 HOC 吗?

Angular 7 : Build Prod Error: Property 'value' does not exist on type 'Component'

C++ 元编程 : A template parameter which *must* inherit an abstract class

macros - Clojure 的宏——定义一个名称由参数组成的绑定(bind)

javascript - VueJs 2.0 将事件从孙子发送到他的祖父组件

javascript - 如何在 ember.js 中相对于单击操作定位模态

javascript - Jquery 在解析时将巨大的数组拆分为许多新的回调

angular - 如何调用不同组件中的方法

ruby-on-rails - 动态定义关注的类和实例方法