index.d.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /**
  2. * Notes about these type definitions:
  3. *
  4. * - Callbacks returning multiple completion values using multiple arguments are not supported by these types.
  5. * Prefer to use Node's style by grouping your values in a single object or array.
  6. * Support for this kind of callback is blocked by Microsoft/TypeScript#5453
  7. *
  8. * - For ease of use, `asyncDone` lets you pass callback functions with a result type `T` instead of `T | undefined`.
  9. * This matches Node's types but can lead to unsound code being typechecked.
  10. *
  11. * The following code typechecks but fails at runtime:
  12. * ```typescript
  13. * async function getString(): Promise<string> {
  14. * return "Hello, World!";
  15. * }
  16. *
  17. * async function evilGetString(): Promise<string> {
  18. * throw new Error("Hello, World!");
  19. * }
  20. *
  21. * function cb(err: Error | null, result: string): void {
  22. * // This is unsound because `result` is `undefined` when `err` is not `null`.
  23. * console.log(result.toLowerCase());
  24. * }
  25. *
  26. * asyncDone(getString, cb); // Prints `hello, world!`
  27. * asyncDone(evilGetString, cb); // Runtime error: `TypeError: Cannot read property 'toLowerCase' of undefined`
  28. * ```
  29. *
  30. * Enforcing stricter callbacks would require developers to use `result?: string` and assert the existence
  31. * of the result either by checking it directly or using the `!` assertion operator after testing for errors.
  32. * ```typescript
  33. * function stricterCb1(err: Error | null, result?: string): void {
  34. * if (err !== null) {
  35. * console.error(err);
  36. * return;
  37. * }
  38. * console.log(result!.toLowerCase());
  39. * }
  40. *
  41. * function stricterCb2(err: Error | null, result?: string): void {
  42. * if (result === undefined) {
  43. * console.error("Undefined result. Error:);
  44. * console.error(err);
  45. * return;
  46. * }
  47. * console.log(result.toLowerCase());
  48. * }
  49. * ```
  50. */
  51. import { ChildProcess } from "child_process";
  52. import { EventEmitter } from "events";
  53. import { Stream } from "stream";
  54. declare namespace asyncDone {
  55. /**
  56. * Represents a callback function used to signal the completion of a
  57. * task without any result value.
  58. */
  59. type VoidCallback = (err: Error | null) => void;
  60. /**
  61. * Represents a callback function used to signal the completion of a
  62. * task with a single result value.
  63. */
  64. interface Callback<T> {
  65. (err: null, result: T): void;
  66. // Use `result?: T` or `result: undefined` to require the consumer to assert the existence of the result
  67. // (even in case of success). See comment at the top of the file.
  68. (err: Error, result?: any): void;
  69. }
  70. /**
  71. * Minimal `Observable` interface compatible with `async-done`.
  72. *
  73. * @see https://github.com/ReactiveX/rxjs/blob/c3c56867eaf93f302ac7cd588034c7d8712f2834/src/internal/Observable.ts#L77
  74. */
  75. interface Observable<T = any> {
  76. subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): any;
  77. }
  78. /**
  79. * Represents an async operation.
  80. */
  81. export type AsyncTask<R = any> =
  82. ((done: VoidCallback) => void)
  83. | ((done: Callback<R>) => void)
  84. | (() => ChildProcess | EventEmitter | Observable<R> | PromiseLike<R> | Stream);
  85. }
  86. /**
  87. * Takes a function to execute (`fn`) and a function to call on completion (`callback`).
  88. *
  89. * @param fn Function to execute.
  90. * @param callback Function to call on completion.
  91. */
  92. declare function asyncDone<R = any>(fn: asyncDone.AsyncTask<R>, callback: asyncDone.Callback<R>): void;
  93. export = asyncDone;