From 9b8b8c433d6ffbdc48b03aa0e39d63dbbae309f7 Mon Sep 17 00:00:00 2001 From: John Yani Date: Wed, 12 Feb 2020 14:13:06 +0200 Subject: [PATCH 1/3] Optional action payload --- src/index.ts | 53 +++++++++++++++++++++--- tests/typings/index.ts | 6 +++ yarn.lock | 92 +++++++++++++----------------------------- 3 files changed, 82 insertions(+), 69 deletions(-) diff --git a/src/index.ts b/src/index.ts index 39738c6..66d5115 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,7 +32,7 @@ export function isType( return action.type === actionCreator.type; } -export interface ActionCreator { +interface ActionCreatorWithPayload { type: string; /** * Identical to `isType` except it is exposed as a bound method of an action @@ -70,14 +70,55 @@ export interface ActionCreator { (payload: Payload, meta?: Meta): Action; } +interface ActionCreatorWithoutPayload { + type: string; + /** + * Identical to `isType` except it is exposed as a bound method of an action + * creator. Since it is bound and takes a single argument it is ideal for + * passing to a filtering function like `Array.prototype.filter` or + * RxJS's `Observable.prototype.filter`. + * + * @example + * + * const somethingHappened = + * actionCreator<{foo: string}>('SOMETHING_HAPPENED'); + * const somethingElseHappened = + * actionCreator<{bar: number}>('SOMETHING_ELSE_HAPPENED'); + * + * if (somethingHappened.match(action)) { + * // action.payload has type {foo: string} + * } + * + * const actionArray = [ + * somethingHappened({foo: 'foo'}), + * somethingElseHappened({bar: 5}), + * ]; + * + * // somethingHappenedArray has inferred type Action<{foo: string}>[] + * const somethingHappenedArray = + * actionArray.filter(somethingHappened.match); + */ + match: (action: AnyAction) => action is Action; + /** + * Creates action without payload. + * + */ + (): Action; +} + +export type ActionCreator = + Payload extends void + ? ActionCreatorWithoutPayload & ActionCreatorWithPayload + : ActionCreatorWithPayload; + export type Success = ( - | {params: Params} - | (Params extends void ? {params?: Params} : never)) & - ({result: Result} | (Result extends void ? {result?: Result} : never)); + (Params extends void ? {params?: Params} : {params: Params})) & + (Result extends void ? {result?: Result} : {result: Result}); export type Failure = ( - | {params: Params} - | (Params extends void ? {params?: Params} : never)) & {error: Error}; + (Params extends void + ? {params?: Params} + : {params: Params})) & {error: Error}; export interface AsyncActionCreators { type: string; diff --git a/tests/typings/index.ts b/tests/typings/index.ts index 4531e3b..75f0909 100644 --- a/tests/typings/index.ts +++ b/tests/typings/index.ts @@ -9,6 +9,7 @@ const actionCreator = actionCreatorFactory(); function testPayload() { const withPayload = actionCreator<{foo: string}>('WITH_PAYLOAD'); const withoutPayload = actionCreator('WITHOUT_PAYLOAD'); + const withOrWithoutPayload = actionCreator('WITH_ORWITHOUT_PAYLOAD') // typings:expect-error const a = withPayload(); @@ -21,6 +22,11 @@ function testPayload() { const f = withoutPayload(undefined, {meta: 'meta'}); // typings:expect-error const g = withoutPayload({foo: 'bar'}); + + const h = withOrWithoutPayload('string'); + //const i = withOrWithoutPayload(); + // typings:expect-error + const j = withOrWithoutPayload(111); } function testAsyncPayload() { diff --git a/yarn.lock b/yarn.lock index 0a8940a..6c20149 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27,11 +27,10 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - dependencies: - color-convert "^1.9.0" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== arr-diff@^2.0.0: version "2.0.0" @@ -47,10 +46,6 @@ array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - babel-code-frame@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" @@ -92,24 +87,6 @@ chalk@^1.1.0: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -color-convert@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" - dependencies: - color-name "^1.1.1" - -color-name@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - colors@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" @@ -143,10 +120,15 @@ defined@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" -diff@^3.1.0, diff@^3.2.0: +diff@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + es-abstract@^1.5.0: version "1.7.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c" @@ -164,7 +146,7 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -290,10 +272,6 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - has@^1.0.1, has@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" @@ -441,20 +419,14 @@ micromatch@^2.3.11: dependencies: brace-expansion "^1.0.0" -minimist@0.0.8, minimist@~0.0.1: +minimist@~0.0.1: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@^1.2.0, minimist@~1.2.0: +minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" -mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - normalize-path@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -598,9 +570,10 @@ semver@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" -source-map-support@^0.5.3: - version "0.5.6" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" +source-map-support@^0.5.6: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -631,12 +604,6 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" - dependencies: - has-flag "^3.0.0" - tape@^4.6.2: version "4.6.3" resolved "https://registry.yarnpkg.com/tape/-/tape-4.6.3.tgz#637e77581e9ab2ce17577e9bd4ce4f575806d8b6" @@ -659,18 +626,16 @@ through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" -ts-node@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-6.0.3.tgz#28bf74bcad134fad17f7469dad04638ece03f0f4" +ts-node@^8.4.0: + version "8.6.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.6.2.tgz#7419a01391a818fbafa6f826a33c1a13e9464e35" + integrity sha512-4mZEbofxGqLL2RImpe3zMJukvEvcO1XP8bj8ozBPySdCUXEcU5cIRwR0aM3R+VoZq7iXc8N86NC0FspGRqP4gg== dependencies: - arrify "^1.0.0" - chalk "^2.3.0" - diff "^3.1.0" + arg "^4.1.0" + diff "^4.0.1" make-error "^1.1.1" - minimist "^1.2.0" - mkdirp "^0.5.1" - source-map-support "^0.5.3" - yn "^2.0.0" + source-map-support "^0.5.6" + yn "3.1.1" tslib@^1.6.0: version "1.7.0" @@ -725,6 +690,7 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -yn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From 0ef37f168906e4a743c194a8eeeed5f0f3965f18 Mon Sep 17 00:00:00 2001 From: John Yani Date: Thu, 13 Feb 2020 12:09:20 +0200 Subject: [PATCH 2/3] Another approach of optional argument --- src/index.ts | 107 ++++++++++++++++++++--------------------- tests/index.ts | 2 + tests/typings/index.ts | 49 ++++++++++++------- 3 files changed, 86 insertions(+), 72 deletions(-) diff --git a/src/index.ts b/src/index.ts index 66d5115..2a7835a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,12 +4,16 @@ export interface AnyAction { export type Meta = null | {[key: string]: any}; -export interface Action extends AnyAction { +export type Action = Payload extends void ? { + type: string; + error?: boolean; + meta?: Meta; +} : { type: string; payload: Payload; error?: boolean; meta?: Meta; -} +}; /** * Returns `true` if action has the same type as action creator. @@ -32,7 +36,7 @@ export function isType( return action.type === actionCreator.type; } -interface ActionCreatorWithPayload { +export interface ActionCreator { type: string; /** * Identical to `isType` except it is exposed as a bound method of an action @@ -67,58 +71,53 @@ interface ActionCreatorWithPayload { * @param payload Action payload. * @param meta Action metadata. Merged with `commonMeta` of Action Creator. */ - (payload: Payload, meta?: Meta): Action; + (...a: (Payload extends void + ? [] | [undefined] | [undefined, Meta] + : [Payload] | [Payload, Meta])): Action; } -interface ActionCreatorWithoutPayload { - type: string; - /** - * Identical to `isType` except it is exposed as a bound method of an action - * creator. Since it is bound and takes a single argument it is ideal for - * passing to a filtering function like `Array.prototype.filter` or - * RxJS's `Observable.prototype.filter`. - * - * @example - * - * const somethingHappened = - * actionCreator<{foo: string}>('SOMETHING_HAPPENED'); - * const somethingElseHappened = - * actionCreator<{bar: number}>('SOMETHING_ELSE_HAPPENED'); - * - * if (somethingHappened.match(action)) { - * // action.payload has type {foo: string} - * } - * - * const actionArray = [ - * somethingHappened({foo: 'foo'}), - * somethingElseHappened({bar: 5}), - * ]; - * - * // somethingHappenedArray has inferred type Action<{foo: string}>[] - * const somethingHappenedArray = - * actionArray.filter(somethingHappened.match); - */ - match: (action: AnyAction) => action is Action; - /** - * Creates action without payload. - * - */ - (): Action; -} - -export type ActionCreator = - Payload extends void - ? ActionCreatorWithoutPayload & ActionCreatorWithPayload - : ActionCreatorWithPayload; +type EmptyObject = { + [K in any] : never; +}; -export type Success = ( - (Params extends void ? {params?: Params} : {params: Params})) & - (Result extends void ? {result?: Result} : {result: Result}); +export type Success = + Params extends void + ? ( + Result extends void + ? EmptyObject + : { + result: Result; + } + ) + : ( + Result extends void ? { + params: Params; + }: { + params: Params; + result: Result; + } + ) +; export type Failure = ( - (Params extends void - ? {params?: Params} - : {params: Params})) & {error: Error}; + Params extends void + ? ( + Error extends void + ? EmptyObject + : { + error: Error; + } + ) + : ( + Error extends void + ? { + params: Params; + }: { + params: Params; + error: Error; + } + ) +); export interface AsyncActionCreators { type: string; @@ -197,7 +196,7 @@ export function actionCreatorFactory( function actionCreator( type: string, commonMeta?: Meta, - isError: ((payload: Payload) => boolean) | boolean = defaultIsError, + isError: ((payload?: Payload) => boolean) | boolean = defaultIsError, ) { const fullType = base + type; @@ -209,11 +208,11 @@ export function actionCreatorFactory( } return Object.assign( - (payload: Payload, meta?: Meta) => { - const action: Action = { + (payload?: Payload, meta?: Meta) => { + const action = { type: fullType, payload, - }; + } as Action; if (commonMeta || meta) { action.meta = Object.assign({}, commonMeta, meta); diff --git a/tests/index.ts b/tests/index.ts index 4c1cc96..8f89d18 100644 --- a/tests/index.ts +++ b/tests/index.ts @@ -56,6 +56,8 @@ test('meta', assert => { const someAction = actionCreator('ACTION_TYPE'); + const actionWithoutPayload = someAction(); + const action = someAction(undefined, {foo: 'bar'}); assert.deepEqual(action.meta, {foo: 'bar'}); diff --git a/tests/typings/index.ts b/tests/typings/index.ts index 75f0909..67e0e76 100644 --- a/tests/typings/index.ts +++ b/tests/typings/index.ts @@ -1,4 +1,4 @@ -import actionCreatorFactory, {isType, AnyAction} from "typescript-fsa"; +import actionCreatorFactory, {isType, AnyAction, AsyncActionCreators, Success} from "typescript-fsa"; declare const action: AnyAction; @@ -9,7 +9,7 @@ const actionCreator = actionCreatorFactory(); function testPayload() { const withPayload = actionCreator<{foo: string}>('WITH_PAYLOAD'); const withoutPayload = actionCreator('WITHOUT_PAYLOAD'); - const withOrWithoutPayload = actionCreator('WITH_ORWITHOUT_PAYLOAD') + const withOrWithoutPayload = actionCreator('WITH_ORWITHOUT_PAYLOAD') // typings:expect-error const a = withPayload(); @@ -24,7 +24,7 @@ function testPayload() { const g = withoutPayload({foo: 'bar'}); const h = withOrWithoutPayload('string'); - //const i = withOrWithoutPayload(); + const i = withOrWithoutPayload(); // typings:expect-error const j = withOrWithoutPayload(111); } @@ -176,34 +176,39 @@ function testAsyncNoParamsAndResult() { }); } -function testAsyncGeneric(params: P, result: R) { +function testAsyncGeneric(...params: P extends void ? [] | [undefined] | [undefined, R] : [P] | [P, R]) { const async = actionCreator.async('ASYNC'); - const started = async.started(params); + const started = async.started(...params); + // typings:expect-error const started1 = async.started({}); // typings:expect-error const started2 = async.started(); - - const done = async.done({ - params, - result, - }); +/* + if(params.length == 2 && params[0] !== undefined && params[1] !== undefined) { + const done = async.done({ + params: params[0], + result: params[1], + }); + } +*/ // typings:expect-error const done1 = async.done({ params: {foo: 1}, - result, + result: params[1], }); // typings:expect-error const done2 = async.done({ - params, + params: params[0], result: {bar: 1}, }); - +/* const failed = async.failed({ - params, + params: params[0], error: {baz: 'baz'}, }); +*/ // typings:expect-error const failed1 = async.failed({ params: {foo: 1}, @@ -211,19 +216,26 @@ function testAsyncGeneric(params: P, result: R) { }); } +var voidValue = (function () { })(); + function testAsyncGenericStrictError(params: P, result: R, error: E) { const async = actionCreator.async('ASYNC'); - const started = async.started(params); +/* + if(params === null || params === undefined) { + const started = async.started(); + } +*/ // typings:expect-error const started1 = async.started({}); // typings:expect-error const started2 = async.started(); - +/* const done = async.done({ params, result, - }); + } as Success); +*/ // typings:expect-error const done1 = async.done({ params: {foo: 1}, @@ -234,11 +246,12 @@ function testAsyncGenericStrictError(params: P, result: R, error: E) { params, result: {bar: 1}, }); - +/* const failed = async.failed({ params, error, }); +*/ // typings:expect-error const failed1 = async.failed({ params: {foo: 1}, From 56c3b35c6e1399c3d58067bf61de80c2557cfa4b Mon Sep 17 00:00:00 2001 From: John Yani Date: Thu, 13 Feb 2020 14:18:00 +0200 Subject: [PATCH 3/3] Fix generic examples --- src/index.ts | 13 +++++------ tests/typings/index.ts | 51 +++++++++++++++++++++--------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2a7835a..767c95a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -71,9 +71,8 @@ export interface ActionCreator { * @param payload Action payload. * @param meta Action metadata. Merged with `commonMeta` of Action Creator. */ - (...a: (Payload extends void - ? [] | [undefined] | [undefined, Meta] - : [Payload] | [Payload, Meta])): Action; + (...a: (Payload extends void ? []: never)): Action; + (params: Payload, meta?: Meta): Action; } type EmptyObject = { @@ -92,11 +91,11 @@ export type Success = : ( Result extends void ? { params: Params; - }: { + } : never) + | { params: Params; result: Result; } - ) ; export type Failure = ( @@ -112,11 +111,11 @@ export type Failure = ( Error extends void ? { params: Params; - }: { + }: never) + | { params: Params; error: Error; } - ) ); export interface AsyncActionCreators { diff --git a/tests/typings/index.ts b/tests/typings/index.ts index 67e0e76..3e7a65a 100644 --- a/tests/typings/index.ts +++ b/tests/typings/index.ts @@ -1,4 +1,4 @@ -import actionCreatorFactory, {isType, AnyAction, AsyncActionCreators, Success} from "typescript-fsa"; +import actionCreatorFactory, {isType, AnyAction, AsyncActionCreators, Success, Failure} from "typescript-fsa"; declare const action: AnyAction; @@ -176,23 +176,23 @@ function testAsyncNoParamsAndResult() { }); } -function testAsyncGeneric(...params: P extends void ? [] | [undefined] | [undefined, R] : [P] | [P, R]) { - const async = actionCreator.async('ASYNC'); +function testAsyncGeneric(params: P, result: R) { + const async = actionCreator.async('ASYNC'); - const started = async.started(...params); + const started = async.started(params); // typings:expect-error const started1 = async.started({}); // typings:expect-error const started2 = async.started(); -/* - if(params.length == 2 && params[0] !== undefined && params[1] !== undefined) { + + if(params !== undefined && result !== undefined) { const done = async.done({ - params: params[0], - result: params[1], - }); + params, + result, + } as Success); } -*/ + // typings:expect-error const done1 = async.done({ params: {foo: 1}, @@ -203,12 +203,14 @@ function testAsyncGeneric(...params: P extends void ? [] | [undefined] | [ params: params[0], result: {bar: 1}, }); -/* - const failed = async.failed({ - params: params[0], - error: {baz: 'baz'}, - }); -*/ + + if(params !== undefined) { + const failed = async.failed({ + params, + error: {baz: 'baz'}, + } as Failure); + } + // typings:expect-error const failed1 = async.failed({ params: {foo: 1}, @@ -221,21 +223,20 @@ var voidValue = (function () { })(); function testAsyncGenericStrictError(params: P, result: R, error: E) { const async = actionCreator.async('ASYNC'); -/* - if(params === null || params === undefined) { - const started = async.started(); + if(params === undefined) { + const started = (async as AsyncActionCreators as AsyncActionCreators).started(); } -*/ + // typings:expect-error const started1 = async.started({}); // typings:expect-error const started2 = async.started(); -/* + const done = async.done({ params, result, } as Success); -*/ + // typings:expect-error const done1 = async.done({ params: {foo: 1}, @@ -246,12 +247,12 @@ function testAsyncGenericStrictError(params: P, result: R, error: E) { params, result: {bar: 1}, }); -/* + const failed = async.failed({ params, error, - }); -*/ + } as Failure); + // typings:expect-error const failed1 = async.failed({ params: {foo: 1},