Last active
September 3, 2021 14:56
-
-
Save intrnl/a7cc9a0864e130d9740e9b7baa2c3c08 to your computer and use it in GitHub Desktop.
Tree-shakeable class methods
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Module } from './module'; | |
export class Foo extends Module { | |
_foo = 'foo'; | |
} | |
export class Bar extends Module { | |
_bar = 'bar'; | |
} | |
export function fooOnly (foo: Foo, str: string) { | |
return foo._foo; | |
} | |
export function barOnly (bar: Bar, num: number) { | |
return bar._bar; | |
} | |
let foo = new Foo(); | |
foo.do(fooOnly, ''); // should pass | |
foo.do(barOnly, 0); // should fail | |
let bar = new Bar(); | |
bar.do(fooOnly, ''); // should fail | |
bar.do(barOnly, 0); // should pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type Extension<T> = (mod: T, ...args: any[]) => any; | |
export type ExtensionParameters<T extends (mod: any, ...args: any[]) => any> = | |
T extends (mod: any, ...args: infer P) => any ? P : never; | |
export abstract class Module { | |
do<T extends Extension<this>> (fn: T, ...args: ExtensionParameters<T>): ReturnType<T> { | |
return fn(this, ...args); | |
} | |
} |
Treeshake-able IndexedDB key value store
export class IDBKeyval extends Module {
_idb: Promise<IDBDatabase>;
_name: string;
constructor (db = 'keyval-store', store = 'store') {
super();
this._name = store;
this._idb = new Promise((resolve, reject) => {
const request = indexedDB.open(db);
request.onupgradeneeded = () => request.result.createObjectStore(store);
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve(request.result);
});
}
}
function perform<T> (store: IDBKeyval, mode: IDBTransactionMode, callback: (store: IDBObjectStore) => T | PromiseLike<T>): Promise<void> {
return store._idb.then((db) => new Promise((resolve, reject) => {
const transaction = db.transaction(store._name, mode);
transaction.oncomplete = () => resolve();
transaction.onerror = transaction.onabort = () => reject(transaction.error);
callback(transaction.objectStore(store._name));
}))
}
export function get<T> (store: IDBKeyval, key: IDBValidKey): Promise<T> {
let request: IDBRequest<T>;
return perform(store, 'readonly', (store) => request = store.get(key))
.then(() => request.result);
}
export function keys (store: IDBKeyval): Promise<IDBValidKey[]> {
let request: IDBRequest<IDBValidKey[]>;
return perform(store, 'readonly', (store) => request = store.getAllKeys())
.then(() => request.result)
}
export function set<T> (store: IDBKeyval, key: IDBValidKey, value: T): Promise<void> {
return perform(store, 'readwrite', (store) => store.put(value, key));
}
export function remove (store: IDBKeyval, key: IDBValidKey): Promise<void> {
return perform(store, 'readwrite', (store) => store.delete(key));
}
export function clear (store: IDBKeyval): Promise<void> {
return perform(store, 'readwrite', (store) => store.clear());
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based on this HTTP 203 video, wanting to see if TypeScript authoring is possible.
Class methods has the instance on the first parameter, instead of relying on
this
, which makes it possible to author them in arrow functions, or even easily opt out from using thedo
method entirely.