Created
February 17, 2019 15:49
-
-
Save felixfbecker/7116bc7766bc24ae25140554867ff338 to your computer and use it in GitHub Desktop.
Comlink types
This file contains hidden or 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
// To avoid Promise<Promise<T>> | |
type Promisify<T> = Promise<Unpromisify<T>>; | |
type Unpromisify<P> = P extends Promise<infer T> ? T : P; | |
/** | |
* Symbol that gets added to objects by `Comlink.proxy()`. | |
*/ | |
export const proxyValueSymbol = Symbol("comlinkProxyValue"); | |
/** | |
* Object that was wrapped with `Comlink.proxy()`. | |
*/ | |
export interface ProxyValue { | |
[proxyValueSymbol]: true; | |
} | |
/** | |
* Returns true if the given value has the proxy value symbol added to it. | |
*/ | |
const isProxyValue = (value: any): value is ProxyValue => | |
!!value && value[proxyValueSymbol] === true; | |
// This needs to be its own type alias, otherwise it will not distribute over unions | |
// https://www.typescriptlang.org/docs/handbook/advanced-types.html#distributive-conditional-types | |
type ProxyProperty<T> = T extends Function | ProxyValue | |
? ProxyResult<T> | |
: Promisify<T>; | |
type UnproxyProperty<T> = T extends Function | ProxyValue | |
? ProxyInput<T> | |
: Unpromisify<T>; | |
/** | |
* `ProxiedObject<T>` is equivalent to `T`, except that all properties are now promises and | |
* all functions now return promises, except if they were wrapped with `Comlink.proxyValue()`. | |
* It effectively async-ifies an object. | |
*/ | |
export type ProxiedObject<T> = { [P in keyof T]: ProxyProperty<T[P]> }; | |
/** | |
* Inverse of `ProxiedObject<T>` | |
*/ | |
export type UnwrapProxiedObject<T> = { [P in keyof T]: UnproxyProperty<T[P]> }; | |
/** | |
* Proxies `T` if it is a ProxyValue, clones it otherwise. | |
*/ | |
export type ProxyOrClone<T> = T extends ProxyValue ? ProxyResult<T> : T; | |
export type UnproxyOrClone<T> = T extends ProxiedObject<ProxyValue> | |
? ProxyInput<T> | |
: T; | |
/** | |
* The inverse of `ProxyResult<T>`. | |
* Takes a `ProxyResult<T>` and returns its original input `T`. | |
*/ | |
export type ProxyInput<R> = UnwrapProxiedObject<R> & | |
(R extends (...args: infer Arguments) => infer R | |
? ( | |
...args: { [I in keyof Arguments]: ProxyOrClone<Arguments[I]> } | |
) => | |
| UnproxyOrClone<Unpromisify<R>> | |
| Promise<UnproxyOrClone<Unpromisify<R>>> | |
: unknown); | |
/** | |
* `ProxyResult<T>` is an augmentation of `ProxyObject<T>` that also handles raw functions | |
* and classes correctly. | |
*/ | |
export type ProxyResult<T> = ProxiedObject<T> & | |
(T extends (...args: infer Arguments) => infer R | |
? ( | |
...args: { [I in keyof Arguments]: UnproxyOrClone<Arguments[I]> } | |
) => Promisify<ProxyOrClone<R>> | |
: unknown) & | |
(T extends { new (...args: infer ArgumentsType): infer InstanceType } | |
? { | |
new ( | |
...args: { | |
[I in keyof ArgumentsType]: UnproxyOrClone<ArgumentsType[I]> | |
} | |
): Promisify<ProxiedObject<InstanceType>>; | |
} | |
: unknown); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment