🤖 Merge PR #46276 feat: Add regenerator‑runtime type definition by @ExE-Boss

* feat: Add `regenerator‑runtime` type definition

* fix(regenerator‑runtime/mark): Preserve overloads

* fix(regenerator‑runtime): Improve order of `context.abrupt(…)` inference

* fix(regenerator‑runtime): Fix `AsyncIterator.next` signature
This commit is contained in:
ExE Boss 2020-07-29 18:07:01 +02:00 committed by GitHub
parent bfc7f17b44
commit 2bcf3bdca4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 426 additions and 0 deletions

236
types/regenerator-runtime/index.d.ts vendored Normal file
View File

@ -0,0 +1,236 @@
// Type definitions for regenerator-runtime 0.13
// Project: https://github.com/facebook/regenerator
// Definitions by: ExE Boss <https://github.com/ExE-Boss>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// Minimum TypeScript Version: 3.6
export as namespace regeneratorRuntime;
declare global {
var regeneratorRuntime: typeof import('.');
}
/**
* The implementation of the generator.
*/
export type InnerFunction<T = undefined, TYield = unknown, TReturn = unknown, TNext = unknown> = (
this: T,
context: Context<TYield, TReturn, TNext>,
) => unknown;
export type ContextLocation = number | 'end';
export type CompletionType = 'normal' | 'return' | 'throw' | 'break' | 'continue';
// prettier-ignore
export type TryLocationsList = ReadonlyArray<
| readonly [number, number]
| readonly [number, number | undefined, number, ContextLocation]
>;
export interface CompletionRecord {
type: CompletionType;
arg: unknown;
}
export interface TryEntry {
readonly tryLoc: number;
readonly catchLoc?: number;
readonly finallyLoc?: number;
readonly afterLoc?: ContextLocation;
completion?: CompletionRecord;
}
export interface DelegatedIterator {
iterator: Iterator<unknown, unknown, unknown>;
}
export interface Context<TYield = unknown, TReturn = unknown, TNext = unknown> {
readonly tryEntries: readonly [
{ readonly tryLoc: 'root' } & Omit<TryEntry, 'tryLoc'>,
...TryEntry[]
];
/**
* The value passed to `next()`.
*/
sent: TNext;
/**
* The label of the previous location, needs to be set to `next` at the start of user code.
*/
prev: unknown;
/**
* The label of the next location, is set to `'end'` when the generator needs to close abruptly.
*/
next: number | 'end';
/**
* Whether the generator has finished.
*/
done: boolean;
/**
* The return value, set by `abrupt("return")`.
*/
rval: TReturn;
/**
* If truthy, then it contains information about the currently `yield*` delegated iterator.
*/
delegate: DelegatedIterator | undefined;
/**
* The generator method.
*/
method: 'next' | 'return' | 'throw';
/**
* The argument passed to the generator method.
*/
arg: unknown;
reset(skipTempReset?: boolean): void;
/**
* Ends the iteration.
*/
stop(): TReturn;
/**
* Dispatches an exception to `innerFn`
*
* @param exception The exception to dispatch.
*/
dispatchException(exception: unknown): boolean;
/**
* @param type The completion type.
* @param rval The return value.
*/
abrupt(type: 'return', rval?: TReturn): unknown;
/**
* @param type The completion type.
* @param exception The exception to throw.
*/
abrupt(type: 'throw', exception?: unknown): never;
/**
* @param type The completion type.
* @param nextLoc The location label to resume iteration at.
*/
abrupt(type: 'break' | 'continue', nextLoc: number): unknown;
/**
* @param type The completion type.
* @param arg The [[Value]] or [[Target]] of the completion record.
*/
abrupt(type: CompletionType, arg?: unknown): unknown;
/**
* @param record The completion record.
* @param afterLoc The location to resume the generator at, only used by normal completions.
*/
complete(record: Readonly<CompletionRecord>, afterLoc?: ContextLocation): unknown;
/**
* Used to signify the end of a finally block.
*
* @param finallyLoc The label of the beginning of the finally block.
*/
finish(finallyLoc: number): unknown;
/**
* Used to obtain the exception that was thrown in the associated try block.
*
* @param tryLoc The label of the beginning of the try block.
*/
catch(tryLoc: number): unknown;
/**
* @param iterable The iterable to delegate to.
* @param resultName The name of the property to assign to on this context.
* @param nextLoc The label of the location where to resume iteration.
*/
delegateYield(
iterable: { [Symbol.iterator](): Iterator<TYield, unknown, unknown> },
resultName: string,
nextLoc: ContextLocation,
): unknown;
[
/**
* Expects properties to match `/^t[+-]?\d*(?:(?<=\d)\.\d*|\.\d+)?(?:e[+-]?\d+)?$/`.
*/
temp: string
]: any;
}
export function wrap<T = undefined, TYield = unknown, TReturn = unknown, TNext = unknown>(
innerFn: InnerFunction<T, TYield, TReturn, TNext>,
// tslint:disable-next-line: ban-types
outerFn?: Function | null,
self?: T,
tryLocsList?: TryLocationsList,
): Generator<TYield, TReturn, TNext>;
export interface ResolvablePromiseConstructorLike extends PromiseConstructorLike {
resolve<T = void>(value?: T): PromiseLike<T>;
}
export class AsyncIterator<TYield = unknown, TReturn = unknown, TNext = unknown>
implements AsyncGenerator<TYield, TReturn, TNext> {
constructor(
generator: Generator<
TYield | PromiseLike<TYield> | awrap<unknown>,
TReturn | PromiseLike<TReturn> | awrap<unknown>
>,
PromiseImpl: ResolvablePromiseConstructorLike,
);
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
next(...args: [] | [TNext]): Promise<IteratorResult<TYield, TReturn>>;
return(value: TReturn | PromiseLike<TReturn>): Promise<IteratorResult<TYield, TReturn>>;
throw(e: any): Promise<IteratorResult<TYield, TReturn>>;
[Symbol.asyncIterator](): this;
}
export function async<T = undefined, TYield = unknown, TReturn = unknown>(
innerFn: InnerFunction<T, TYield, TReturn>,
outerFn: GeneratorFunction,
self?: T,
tryLocsList?: TryLocationsList,
PromiseImpl?: ResolvablePromiseConstructorLike,
): AsyncIterator<
TYield extends PromiseLike<infer Await> ? Await : Exclude<TYield, awrap<unknown>>,
TReturn extends PromiseLike<infer Await> ? Await : Exclude<TReturn, awrap<unknown>>
>;
export function async<T = undefined, TReturn = unknown>(
innerFn: InnerFunction<T, unknown, TReturn>,
// tslint:disable-next-line: ban-types
outerFn?: Function | null,
self?: T,
tryLocsList?: TryLocationsList,
PromiseImpl?: ResolvablePromiseConstructorLike,
): Promise<TReturn extends PromiseLike<infer Await> ? Await : TReturn>;
export function awrap<V>(arg: V): awrap<V>;
export class awrap<V> {
constructor(arg: V);
// Used to tell TypeScript that this class is to be treated as a nominal type:
private readonly '#private';
readonly __await: V;
}
export function isGeneratorFunction(func: unknown): func is GeneratorFunction;
export function keys(object: {}): () => IteratorResult<string, undefined>;
// tslint:disable-next-line: ban-types
export function mark<F extends Function>(genFun: F): F & GeneratorFunction;
export function values<I extends Iterator<unknown, unknown, unknown>>(iterable: { [Symbol.iterator](): I }): I;
export function values<T>(iterableOrArrayLike: Iterable<T> | ArrayLike<T>): Iterator<T, unknown, unknown>;

View File

@ -0,0 +1,167 @@
import regenerator = require('regenerator-runtime');
/**
* The `expectType` function from https://www.npmjs.com/package/tsd,
* except instead of returning `void`, it returns `T`.
*/
declare function expectType<T>(value: T): T;
expectType<typeof regenerator>(regeneratorRuntime);
expectType<typeof regeneratorRuntime>(regenerator);
declare const number: number;
declare const anyArray: object[];
declare const anyArrayLike: ArrayLike<object>;
declare const anyIterable: Iterable<object>;
declare const anyIterableIterator: IterableIterator<object>;
declare const anyGenerator: Generator<object, object, object>;
regenerator.values(anyArray); // $ExpectType IterableIterator<object>
expectType<Iterator<object>>(regenerator.values(anyIterable));
regenerator.values(anyIterableIterator); // $ExpectType IterableIterator<object>
regenerator.values(anyGenerator); // $ExpectType Generator<object, object, object>
regenerator.values(anyArrayLike); // $ExpectType Iterator<object, unknown, unknown>
regenerator.keys(anyArray); // $ExpectType () => IteratorResult<string, undefined>
regenerator.keys(anyIterableIterator); // $ExpectType () => IteratorResult<string, undefined>
regenerator.AsyncIterator.prototype.next; // $ExpectType (...args: [] | [any]) => Promise<IteratorResult<any, any>>
regenerator.AsyncIterator.prototype.return; // $ExpectType (value: any) => Promise<IteratorResult<any, any>>
regenerator.AsyncIterator.prototype.throw; // $ExpectType (e: any) => Promise<IteratorResult<any, any>>
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.map
function IteratorMap<T, U, TNext = unknown>(
this: Iterator<T, unknown, TNext>,
mapper: (value: T) => U,
): Generator<U, void, TNext> {
// Prelude steps:
// 1. Let iterated be ? GetIteratorDirect(this value).
const iterated = GetIteratorDirect(this); // $ExpectType IteratorRecord<Iterator<T, unknown, TNext>>
// 2. If IsCallable(mapper) is false, throw a TypeError exception.
if (typeof mapper !== 'function') {
throw new TypeError(`${mapper} is not a function`);
}
// Body steps:
// 1. Let lastValue be undefined.
let lastValue: unknown;
let next: false | IteratorYieldResult<T>;
let value: T;
// 2. Repeat,
return regenerator.wrap(
// This is roughly based on the output of `@babel/plugin-transform-regenerator`:
function IteratorMapBody(this: Iterator<T, unknown, TNext>, context: regenerator.Context<U, void, TNext>) {
this; // $ExpectType Iterator<T, unknown, TNext>
context; // $ExpectType Context<U, void, TNext>
context.tryEntries[0].tryLoc; // $ExpectType "root"
context.tryEntries[1].tryLoc; // $ExpectType number
context.tryEntries[number].tryLoc; // $ExpectType number | "root"
while (true) {
switch ((context.prev = context.next)) {
case 0:
// a. Let next be ? IteratorStep(iterated, lastValue).
next = IteratorStep(iterated, lastValue);
// b. If next is false, return undefined.
if (!next) {
context.next = 'end';
break;
}
// c. Let value be ? IteratorValue(next).
value = IteratorValue(next);
// try {
case 1:
context.prev = 1;
context.next = 2;
// d. Let mapped be Call(mapper, undefined, « value »).
// e. IfAbruptCloseIterator(iterated, mapped).
return Call(mapper, undefined, [value]);
case 2:
// f. Set lastValue to Yield(mapped).
// g. IfAbruptCloseIterator(iterated, lastValue).
lastValue = context.sent;
context.next = 4;
break;
// } catch (context.t0) {
case 3:
context.prev = 3;
context.t0 = context.catch(1);
return context.abrupt(
'return',
IteratorClose(iterated, () => {
throw context.t0;
}),
);
// }
case 4:
context.next = 0;
break;
case 'end':
// tslint:disable-next-line: no-void-expression
return context.stop();
}
}
},
IteratorMap,
this,
[[1, 3]],
);
}
declare const overloadedFunction: {
(): Generator;
<T>(...args: T[]): Generator<T>;
};
// $ExpectType { (): Generator<unknown, any, unknown>; <T>(...args: T[]): Generator<T, any, unknown>; } & GeneratorFunction
regenerator.mark(overloadedFunction);
declare const mappableIterator: IterableIterator<object> & {
map: typeof IteratorMap;
};
// $ExpectType Generator<string | awrap<Promise<any>>, void, undefined>
const mappedIterator = mappableIterator.map(value => {
value; // $ExpectType object
return value instanceof Promise ? regenerator.awrap(value) : String(value);
});
// $ExpectType AsyncIterator<string, void, unknown>
new regenerator.AsyncIterator(mappedIterator, Promise);
interface IteratorRecord<I extends Iterator<unknown, unknown, unknown>> {
'[[Iterator]]': I;
'[[NextMethod]]': I['next'];
'[[Done]]': boolean;
}
declare function GetIteratorDirect<I extends Iterator<unknown, unknown, unknown>>(iterator: I): IteratorRecord<I>;
declare function IteratorClose<T>(
iteratorRecord: IteratorRecord<Iterator<unknown, unknown, unknown>>,
completion: () => T,
): T;
declare function IteratorStep<T>(IteratorRecord: IteratorRecord<Iterator<T>>): false | IteratorYieldResult<T>;
declare function IteratorStep<T, TNext = unknown>(
IteratorRecord: IteratorRecord<Iterator<T, unknown, TNext>>,
value: TNext,
): false | IteratorYieldResult<T>;
declare function IteratorValue<T = never, TReturn = never>(result: IteratorResult<T, TReturn>): T | TReturn;
declare function Call<T, R>(F: (this: T) => R, thisArg: T): R;
declare function Call<T, A extends readonly unknown[], R>(
F: (this: T, ...args: A) => R,
thisArg: T,
args: Readonly<A>,
): R;

View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"ESNext"
],
"target": "ESNext",
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": ["../"],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"regenerator-runtime-tests.ts",
"index.d.ts"
]
}

View File

@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }