async-off
: make asynchronous TypeScript code synchronous
Installation
Using without installation:
npx async-off path/to/file.ts
Installation:
npm install -g async-off
Usage
async-off path/to/file.ts
cat path/to/file.ts | async-off
async-off --help
async-off -h
async-off
converts asynchronous TypeScript code to synchronous code by:
- Removing the keyword
await
in expressions and in for-await-of
loops.
- Removing the keyword
async
.
- Changing
Promise<X>
to X
.
- Changing
AsyncIterable<X>
to Iterable<X>
and AsyncIterator<X>
to Iterator<X>
.
More changes can be configured (see below).
What would I use this command for?
async-off
’s approach only works for very simple code. Then you can avoid writing very similar code twice – once asynchronously and once synchronously. Examples of such code include:
- Helper functions for iterables:
map()
, filter()
, etc. (see next section)
- A Markdown parser that can be used both asynchronously (with asynchronous iterables as input) and synchronously (with strings or normal iterables as input).
Example
Input:
async function* map<In, Out>(
mapperFn: (x: In) => Out,
iterable: AsyncOrSyncIterable<In>
): AsyncIterable<Out> {
for await (const x of iterable) {
yield mapperFn(x);
}
}
type AsyncOrSyncIterable<Item> = AsyncIterable<Item> | Iterable<Item>;
Output:
function* map<In, Out>(
mapperFn: (x: In) => Out,
iterable: Iterable<In>
): Iterable<Out> {
for (const x of iterable) {
yield mapperFn(x);
}
}
Configuration
async-off
is configured via embedded JSON (see previous section). The following properties are supported:
interface ConfigJson {
unwrapFunctionCall?: Array<string>;
unwrapParamerizedType?: Array<string>;
renameVariable?: Record<string, string>;
renameType?: Record<string, string>;
}
Tips
Different names for exports
const Functions = {
map,
filter,
};
export {Functions as AsyncIterable};
Resources
- For syntax transformations,
async-off
uses the library ts-morph
- The TypeScript AST Viewer helps with exploring how TypeScript code is represented as abstract syntax trees.