113 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * Notes about these type definitions:
 | |
|  *
 | |
|  * - Callbacks returning multiple completion values using multiple arguments are not supported by these types.
 | |
|  *   Prefer to use Node's style by grouping your values in a single object or array.
 | |
|  *   Support for this kind of callback is blocked by Microsoft/TypeScript#5453
 | |
|  *
 | |
|  * - For ease of use, `asyncDone` lets you pass callback functions with a result type `T` instead of `T | undefined`.
 | |
|  *   This matches Node's types but can lead to unsound code being typechecked.
 | |
|  *
 | |
|  *   The following code typechecks but fails at runtime:
 | |
|  *   ```typescript
 | |
|  *   async function getString(): Promise<string> {
 | |
|  *     return "Hello, World!";
 | |
|  *   }
 | |
|  *
 | |
|  *   async function evilGetString(): Promise<string> {
 | |
|  *     throw new Error("Hello, World!");
 | |
|  *   }
 | |
|  *
 | |
|  *   function cb(err: Error | null, result: string): void {
 | |
|  *     // This is unsound because `result` is `undefined` when `err` is not `null`.
 | |
|  *     console.log(result.toLowerCase());
 | |
|  *   }
 | |
|  *
 | |
|  *   asyncDone(getString, cb); // Prints `hello, world!`
 | |
|  *   asyncDone(evilGetString, cb); // Runtime error: `TypeError: Cannot read property 'toLowerCase' of undefined`
 | |
|  *   ```
 | |
|  *
 | |
|  *   Enforcing stricter callbacks would require developers to use `result?: string` and assert the existence
 | |
|  *   of the result either by checking it directly or using the `!` assertion operator after testing for errors.
 | |
|  *   ```typescript
 | |
|  *   function stricterCb1(err: Error | null, result?: string): void {
 | |
|  *     if (err !== null) {
 | |
|  *       console.error(err);
 | |
|  *       return;
 | |
|  *     }
 | |
|  *     console.log(result!.toLowerCase());
 | |
|  *   }
 | |
|  *
 | |
|  *   function stricterCb2(err: Error | null, result?: string): void {
 | |
|  *     if (result === undefined) {
 | |
|  *       console.error("Undefined result. Error:);
 | |
|  *       console.error(err);
 | |
|  *       return;
 | |
|  *     }
 | |
|  *     console.log(result.toLowerCase());
 | |
|  *   }
 | |
|  *   ```
 | |
|  */
 | |
| import { ChildProcess } from 'child_process';
 | |
| import { EventEmitter } from 'events';
 | |
| import { Stream } from 'stream';
 | |
| 
 | |
| declare namespace asyncDone {
 | |
|   /**
 | |
|    * Represents a callback function used to signal the completion of a
 | |
|    * task without any result value.
 | |
|    */
 | |
|   type VoidCallback = (err: Error | null | void) => void;
 | |
| 
 | |
|   /**
 | |
|    * Represents a callback function used to signal the completion of a
 | |
|    * task with a single result value.
 | |
|    */
 | |
|   interface Callback<T> {
 | |
|     (err: null, result: T): void;
 | |
| 
 | |
|     // Use `result?: T` or `result: undefined` to require the consumer to assert the existence of the result
 | |
|     // (even in case of success). See comment at the top of the file.
 | |
|     (err: Error, result?: any): void;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Minimal `Observable` interface compatible with `async-done`.
 | |
|    *
 | |
|    * @see https://github.com/ReactiveX/rxjs/blob/c3c56867eaf93f302ac7cd588034c7d8712f2834/src/internal/Observable.ts#L77
 | |
|    */
 | |
|   interface Observable<T = any> {
 | |
|     subscribe(
 | |
|       next?: (value: T) => void,
 | |
|       error?: (error: any) => void,
 | |
|       complete?: () => void
 | |
|     ): any;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Represents an async operation.
 | |
|    */
 | |
|   export type AsyncTask<R = any> =
 | |
|     | ((done: VoidCallback) => void)
 | |
|     | ((done: Callback<R>) => void)
 | |
|     | (() =>
 | |
|         | ChildProcess
 | |
|         | EventEmitter
 | |
|         | Observable<R>
 | |
|         | PromiseLike<R>
 | |
|         | Stream);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Takes a function to execute (`fn`) and a function to call on completion (`callback`).
 | |
|  *
 | |
|  * @param fn Function to execute.
 | |
|  * @param callback Function to call on completion.
 | |
|  */
 | |
| declare function asyncDone<R = any>(
 | |
|   fn: asyncDone.AsyncTask<R>,
 | |
|   callback: asyncDone.Callback<R>
 | |
| ): void;
 | |
| 
 | |
| export = asyncDone;
 |