From e50ee35a7a26a2f87967d7a3535a30bc0bc02845 Mon Sep 17 00:00:00 2001 From: Egor Dydykin Date: Wed, 1 Oct 2025 15:47:47 +0300 Subject: [PATCH] fix: undefined in after falls to extended block result --- docs/typescript-examples/options.ts | 94 +++++++++++++++++++++++++++++ lib/arrayBlock.ts | 12 ++-- lib/block.ts | 70 ++++----------------- lib/compositeBlock.ts | 6 +- lib/firstBlock.ts | 12 ++-- lib/functionBlock.ts | 20 +++--- lib/httpBlock.ts | 12 ++-- lib/index.ts | 42 ++++++------- lib/objectBlock.ts | 20 +++--- lib/pipeBlock.ts | 12 ++-- lib/types.ts | 42 ++++++------- tests/functionBlock.test.ts | 47 +++++++++++++++ tests/httpBlock.test.ts | 6 +- tests/options.after.test.ts | 57 +++++++++++++++++ tests/test.types.ts | 18 ++++++ 15 files changed, 324 insertions(+), 146 deletions(-) create mode 100644 tests/test.types.ts diff --git a/docs/typescript-examples/options.ts b/docs/typescript-examples/options.ts index 490796f..0d639bf 100644 --- a/docs/typescript-examples/options.ts +++ b/docs/typescript-examples/options.ts @@ -270,3 +270,97 @@ const block10 = de.func({ de.run(block10, { params: {}, }); + +export type BlockResultOut< + Result = never, + Before = never, + After = never, +> = +[ After ] extends [ never ] ? + [ Before ] extends [ never ] ? + Result : + Before | Result : + After; + +class Block< + ResultOut extends BlockResultOut, + Result = never, + Before = never, + After = never, +> { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + constructor(options: Options) { + + } + + extend< + ResultOut2 extends BlockResultOut, + BlockResult2 = ResultOut, + Before2 = never, + After2 = never, + >(options: Options) { + return new Block(options); + }; + + run() { + return 1 as ResultOut; + } +} + +export type InferResultOrResult = Result extends Block< +// eslint-disable-next-line @typescript-eslint/no-unused-vars + infer ResultOut, infer After, infer Before, infer Result +> ? InferResultOrResult : Result; + +type Options< + Result = never, + Before = never, + After = never, +> = { + block?: () => Result; + before?: () => Before; + after?: ( + res: [ Before ] extends [ never ] ? + InferResultOrResult : InferResultOrResult | InferResultOrResult + ) => After; +}; + +const block = < + ResultOut extends BlockResultOut, + Result = never, + Before = never, + After = never, +>(options: Options) => { + return new Block(options); +}; + +type Block11Result = { + data: { somefield: number } | null; + errors: Array | null; +}; + +const b1 = block({ + block: (): Block11Result => { + return { data: { somefield: 42 }, errors: null }; + }, + + after: (res) => res, +}); + +const b2 = b1.extend({ + after(res) { + return res.data?.somefield; + }, +}); + +const b3 = b2.extend({ + after(res) { + return res; + }, +}); + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const r1 = b3.run(); + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type R = typeof r1; // оно должно стать number | undefined diff --git a/lib/arrayBlock.ts b/lib/arrayBlock.ts index 4ee9074..ccddeab 100644 --- a/lib/arrayBlock.ts +++ b/lib/arrayBlock.ts @@ -53,9 +53,9 @@ class ArrayBlock< ParamsOut = GetArrayBlockParams, BlockResult = GetArrayBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = GetArrayBlockParams, > extends CompositeBlock< Context, @@ -78,9 +78,9 @@ class ArrayBlock< ExtendedParamsOut extends Params = Params, ExtendedParams = Params, ExtendedBlockResult = ResultOut, - ExtendedBeforeResultOut = undefined, - ExtendedAfterResultOut = undefined, - ExtendedErrorResultOut = undefined, + ExtendedBeforeResultOut = unknown, + ExtendedAfterResultOut = unknown, + ExtendedErrorResultOut = unknown, >({ options }: { options: DescriptBlockOptions< Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams diff --git a/lib/block.ts b/lib/block.ts index d0cf165..5ee8ade 100644 --- a/lib/block.ts +++ b/lib/block.ts @@ -30,23 +30,6 @@ type BlockOptions< 'before' | 'after' | 'error' | 'params' | 'deps' >>; -interface BlockConstructor< - Context, - ParamsOut, - BlockResult, - BeforeResultOut, - AfterResultOut, - ErrorResultOut, - Params, - ClassType, - CustomBlock, -> { - new ({ block, options }: { - block?: CustomBlock; - options: DescriptBlockOptions; - }): ClassType; -} - abstract class BaseBlock< Context, CustomBlock, @@ -54,9 +37,9 @@ abstract class BaseBlock< ResultOut extends BlockResultOut, IntermediateResult, BlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = ParamsOut, > { protected block: CustomBlock; @@ -80,39 +63,6 @@ abstract class BaseBlock< this.initOptions(options); } - protected extendClass< - ClassType, - ExtendedBlockResult, - ExtendedParamsOut extends Params = Params, - ExtendedParams = Params, - ExtendedBeforeResultOut = void, - ExtendedAfterResultOut = void, - ExtendedErrorResultOut = void, - ExtendedCustomBlock extends CustomBlock = CustomBlock, - >({ block, options }: { - block?: ExtendedCustomBlock; - options?: - DescriptBlockOptions< - Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams - >; - }): ClassType { - - return new (> this.constructor)({ - block: this.extendBlock(block) as ExtendedCustomBlock, - options: this.extendOptions(this.options, options), - }); - } - abstract extend< // ExtendedResultOut extends @@ -121,13 +71,19 @@ abstract class BaseBlock< ExtendedParams = Params, // ExtendedCustomBlock = CustomBlock, ExtendedBlockResult = ResultOut, - ExtendedBeforeResultOut = void, - ExtendedAfterResultOut = void, - ExtendedErrorResultOut = void, + ExtendedBeforeResultOut = unknown, + ExtendedAfterResultOut = unknown, + ExtendedErrorResultOut = unknown, >({ block, options }: { block?: CustomBlock; options?: DescriptBlockOptions< - Context, ParamsOut & ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams + Context, + ParamsOut & ExtendedParamsOut, + ExtendedBlockResult, + ExtendedBeforeResultOut, + ExtendedAfterResultOut, + ExtendedErrorResultOut, + ExtendedParams >; }): unknown; diff --git a/lib/compositeBlock.ts b/lib/compositeBlock.ts index d10a104..3c1f936 100644 --- a/lib/compositeBlock.ts +++ b/lib/compositeBlock.ts @@ -24,9 +24,9 @@ abstract class CompositeBlock< IntermediateResult, BlockResultInt, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = ParamsOut, > extends BaseBlock< Context, diff --git a/lib/firstBlock.ts b/lib/firstBlock.ts index 60c8702..24e2db8 100644 --- a/lib/firstBlock.ts +++ b/lib/firstBlock.ts @@ -64,9 +64,9 @@ class FirstBlock< ParamsOut = GetFirstBlockParams, BlockResult = GetFirstBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = GetFirstBlockParams, > extends CompositeBlock< Context, @@ -90,9 +90,9 @@ class FirstBlock< ExtendedParamsOut extends Params = Params, ExtendedParams = Params, ExtendedBlockResult = ResultOut, - ExtendedBeforeResultOut = undefined, - ExtendedAfterResultOut = undefined, - ExtendedErrorResultOut = undefined, + ExtendedBeforeResultOut = unknown, + ExtendedAfterResultOut = unknown, + ExtendedErrorResultOut = unknown, >({ options }: { options: DescriptBlockOptions< Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams diff --git a/lib/functionBlock.ts b/lib/functionBlock.ts index 864529a..a51207d 100644 --- a/lib/functionBlock.ts +++ b/lib/functionBlock.ts @@ -24,9 +24,9 @@ class FunctionBlock< ParamsOut, BlockResult, ResultOut extends BlockResultOut, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = never extends InferParamsOutFromBlock ? ParamsOut : InferParamsOutFromBlock, > extends BaseBlock< Context, @@ -99,12 +99,18 @@ class FunctionBlock< // ExtendedCustomBlock = DescriptHttpBlockDescription, ExtendedBlockResult = ResultOut, - ExtendedBeforeResultOut = undefined, - ExtendedAfterResultOut = undefined, - ExtendedErrorResultOut = undefined, + ExtendedBeforeResultOut = unknown, + ExtendedAfterResultOut = unknown, + ExtendedErrorResultOut = unknown, >({ options }: { options: DescriptBlockOptions< - Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams + Context, + ExtendedParamsOut, + ExtendedBlockResult, + ExtendedBeforeResultOut, + ExtendedAfterResultOut, + ExtendedErrorResultOut, + ExtendedParams >; }) { return new FunctionBlock({ diff --git a/lib/httpBlock.ts b/lib/httpBlock.ts index 0787169..9ef28a6 100644 --- a/lib/httpBlock.ts +++ b/lib/httpBlock.ts @@ -180,9 +180,9 @@ class HttpBlock< HttpResult, ResultOut extends BlockResultOut, BlockResult = DescriptHttpBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = ParamsOut, > extends Block< Context, @@ -205,9 +205,9 @@ class HttpBlock< // ExtendedCustomBlock = DescriptHttpBlockDescription, ExtendedBlockResult = ResultOut, - ExtendedBeforeResultOut = undefined, - ExtendedAfterResultOut = undefined, - ExtendedErrorResultOut = undefined, + ExtendedBeforeResultOut = unknown, + ExtendedAfterResultOut = unknown, + ExtendedErrorResultOut = unknown, >({ options, block }: { block?: DescriptHttpBlockDescription; options?: DescriptBlockOptions< diff --git a/lib/index.ts b/lib/index.ts index 4aa4fef..c17ec09 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -40,9 +40,9 @@ const func = function< ParamsOut, BlockResult, ResultOut extends BlockResultOut, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = ParamsOut, >({ block, options }: { block: FunctionBlockDefinition; @@ -60,9 +60,9 @@ const array = function< ResultOut extends BlockResultOut, ParamsOut = GetArrayBlockParams, BlockResult = GetArrayBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = GetArrayBlockParams, >({ block, options }: { block: ArrayBlockDefinition; @@ -77,9 +77,9 @@ const object = function< ParamsOut = GetObjectBlockParams, BlockResult = GetObjectBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = GetObjectBlockParams, >({ block, options }: { block?: ObjectBlockDefinition; @@ -94,9 +94,9 @@ const http = function< IntermediateResult, BlockResult extends DescriptHttpBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = ParamsOut, >({ block, options }: { block?: DescriptHttpBlockDescription; @@ -113,9 +113,9 @@ const first = function< ResultOut extends BlockResultOut, ParamsOut = GetFirstBlockParams, BlockResult = GetFirstBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = GetFirstBlockParams, >({ block, options }: { block: FirstBlockDefinition; @@ -130,9 +130,9 @@ const pipe = function< ResultOut extends BlockResultOut, ParamsOut = GetPipeBlockParams, BlockResult = GetPipeBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = GetPipeBlockParams, >({ block, options }: { block: PipeBlockDefinition; @@ -152,9 +152,9 @@ const run = function< ResultOut extends BlockResultOut, IntermediateResult, BlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = ParamsOut, >( block: BaseBlock, diff --git a/lib/objectBlock.ts b/lib/objectBlock.ts index d2fafff..5e7500e 100644 --- a/lib/objectBlock.ts +++ b/lib/objectBlock.ts @@ -9,7 +9,7 @@ import type { DescriptBlockDeps } from './depsDomain'; import type DepsDomain from './depsDomain'; export type InferResultFromObjectBlocks = Block extends BaseBlock< -// eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars infer Context, infer CustomBlock, infer ParamsOut, infer ResultOut, infer IntermediateResult, // eslint-disable-next-line @typescript-eslint/no-unused-vars infer BlockResult, infer BeforeResultOut, infer AfterResultOut, infer ErrorResultOut, infer Params @@ -32,10 +32,10 @@ type GetObjectBlockParamsMap> = { export type ObjectBlockDefinition> = { [ P in keyof T ]: T[ P ] extends BaseBlock< - // eslint-disable-next-line @typescript-eslint/no-unused-vars - infer Context, infer CustomBlock, infer ParamsOut, infer ResultOut, infer BlockResult, // eslint-disable-next-line @typescript-eslint/no-unused-vars - infer IntermediateResult, infer BeforeResultOut, infer AfterResultOut, infer ErrorResultOut, infer Params + infer Context, infer CustomBlock, infer ParamsOut, infer ResultOut, infer IntermediateResult, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + infer BlockResult, infer BeforeResultOut, infer AfterResultOut, infer ErrorResultOut, infer Params > ? T[ P ] : never }; @@ -46,9 +46,9 @@ class ObjectBlock< ParamsOut = GetObjectBlockParams, BlockResult = GetObjectBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = GetObjectBlockParams, > extends CompositeBlock< Context, @@ -113,9 +113,9 @@ class ObjectBlock< ExtendedParamsOut extends Params = Params, ExtendedParams = Params, ExtendedBlockResult = ResultOut, - ExtendedBeforeResultOut = undefined, - ExtendedAfterResultOut = undefined, - ExtendedErrorResultOut = undefined, + ExtendedBeforeResultOut = unknown, + ExtendedAfterResultOut = unknown, + ExtendedErrorResultOut = unknown, >({ options }: { options: DescriptBlockOptions< Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams diff --git a/lib/pipeBlock.ts b/lib/pipeBlock.ts index 5ce7e25..e9a607f 100644 --- a/lib/pipeBlock.ts +++ b/lib/pipeBlock.ts @@ -64,9 +64,9 @@ class PipeBlock< ParamsOut = GetPipeBlockParams, BlockResult = GetPipeBlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = GetPipeBlockParams, > extends CompositeBlock< Context, @@ -90,9 +90,9 @@ class PipeBlock< ExtendedParamsOut extends Params = Params, ExtendedParams = Params, ExtendedBlockResult = ResultOut, - ExtendedBeforeResultOut = undefined, - ExtendedAfterResultOut = undefined, - ExtendedErrorResultOut = undefined, + ExtendedBeforeResultOut = unknown, + ExtendedAfterResultOut = unknown, + ExtendedErrorResultOut = unknown, >({ options }: { options: DescriptBlockOptions< Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams diff --git a/lib/types.ts b/lib/types.ts index 3e310a5..20aacc6 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -53,21 +53,21 @@ export type DescriptJSON = export type BlockResultOut< BlockResult, - BeforeResultOut, - AfterResultOut, - ErrorResultOut, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, > = - (never | undefined)extends ErrorResultOut ? - undefined extends AfterResultOut ? - never | undefined extends BeforeResultOut ? + [ unknown ] extends [ Exclude ] ? + [ unknown ] extends [ AfterResultOut ] ? + [ unknown ] extends [ Exclude ] ? BlockResult : - BeforeResultOut | BlockResult : + Exclude | BlockResult : AfterResultOut : - undefined extends AfterResultOut ? - never | undefined extends BeforeResultOut ? - BlockResult | ErrorResultOut : - BeforeResultOut | BlockResult | ErrorResultOut : - AfterResultOut | ErrorResultOut; + [ unknown ] extends [ AfterResultOut ] ? + [ unknown ] extends [ Exclude ] ? + BlockResult | Exclude : + Exclude | BlockResult | Exclude : + AfterResultOut | Exclude; export type InferResultOrResult = Result extends BaseBlock< // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -84,28 +84,28 @@ export type InferResultOrResultOnce = Result extends BaseBlock< > ? ResultOut : Result; export type InferResultFromBlock = Type extends BaseBlock< -// eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars infer Context, infer CustomBlock, infer ParamsOut, infer ResultOut, infer IntermediateResult, // eslint-disable-next-line @typescript-eslint/no-unused-vars infer BlockResult, infer BeforeResultOut, infer AfterResultOut, infer ErrorResultOut, infer Params > ? InferResultOrResult : never; export type InferParamsInFromBlock = Type extends BaseBlock< -// eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars infer Context, infer CustomBlock, infer ParamsOut, infer ResultOut, infer IntermediateResult, // eslint-disable-next-line @typescript-eslint/no-unused-vars infer BlockResult, infer BeforeResultOut, infer AfterResultOut, infer ErrorResultOut, infer Params > ? Params : never; export type InferParamsInFromBlockOrParams = Type extends BaseBlock< -// eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars infer Context, infer CustomBlock, infer ParamsOut, infer ResultOut, infer IntermediateResult, // eslint-disable-next-line @typescript-eslint/no-unused-vars infer BlockResult, infer BeforeResultOut, infer AfterResultOut, infer ErrorResultOut, infer Params > ? Params : P; export type InferParamsOutFromBlock = Type extends BaseBlock< -// eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars infer Context, infer CustomBlock, infer ParamsOut, infer ResultOut, infer IntermediateResult, // eslint-disable-next-line @typescript-eslint/no-unused-vars infer BlockResult, infer BeforeResultOut, infer AfterResultOut, infer ErrorResultOut, infer Params @@ -147,9 +147,9 @@ export interface DescriptBlockOptions< Context, ParamsOut, BlockResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = ParamsOut, > { name?: string; @@ -175,8 +175,8 @@ export interface DescriptBlockOptions< context?: Context; deps: DescriptBlockDeps; cancel: Cancel; - result: (undefined) extends BeforeResultOut ? - InferResultOrResult : InferResultOrResult | InferResultOrResult; + result: [ unknown ] extends [ Exclude ] ? + InferResultOrResult : InferResultOrResult> | InferResultOrResult; }) => AfterResultOut; error?: (args: { diff --git a/tests/functionBlock.test.ts b/tests/functionBlock.test.ts index c8b7324..d2ec3f2 100644 --- a/tests/functionBlock.test.ts +++ b/tests/functionBlock.test.ts @@ -2,6 +2,9 @@ import { describe, expect, it } from 'vitest'; import { getErrorBlock, getResultBlock, waitForValue } from './helpers'; +import ObjectBlock from '../lib/objectBlock'; +import FunctionBlock from '../lib/functionBlock'; + import * as de from '../lib'; // --------------------------------------------------------------------------------------------------------------- // @@ -129,4 +132,48 @@ describe('de.func', () => { expect(e).toBe(cancelReason); }); + // воспроизведение бага с не выведенными параметрами + it.skip('=> de.object params should be infered', () => { + type Params1 = { + param1: number; + }; + + type Params2 = { + param2: number; + }; + + const block = new FunctionBlock({ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + block: ({ params }) => { + const x = new ObjectBlock({ + block: { + block1: de.func({ + block: ({ params }: { params: Params1 }) => { + return params; + }, + }), + + block2: de.func({ + block: ({ params }: { params: Params2 }) => { + return params; + }, + }), + }, + }); + + return x; + }, + + options: { + params: ({ params }) => params, + }, + }); + + de.run(block, { + params: { + param1: 1, + param2: '2', + }, + }); + }); }); diff --git a/tests/httpBlock.test.ts b/tests/httpBlock.test.ts index 914f0ee..8702675 100644 --- a/tests/httpBlock.test.ts +++ b/tests/httpBlock.test.ts @@ -33,9 +33,9 @@ describe('http', < BlockResult extends DescriptHttpBlockResult, HTTPResult, - BeforeResultOut = undefined, - AfterResultOut = undefined, - ErrorResultOut = undefined, + BeforeResultOut = unknown, + AfterResultOut = unknown, + ErrorResultOut = unknown, Params = ParamsOut, >({ block, options }: { block?: DescriptHttpBlockDescription; diff --git a/tests/options.after.test.ts b/tests/options.after.test.ts index da433e8..6e43b51 100644 --- a/tests/options.after.test.ts +++ b/tests/options.after.test.ts @@ -2,6 +2,8 @@ import { describe, expect, it, vi } from 'vitest'; import * as de from '../lib'; +import type { Expect, TypesMatch } from './test.types'; + import { getErrorBlock, getResultBlock, waitForError, waitForValue } from './helpers'; describe('options.after', () => { @@ -433,4 +435,59 @@ describe('options.after', () => { expect(result).toBe(afterResult); }); + it('types test for after that return maybe undefined', async() => { + type BlockResult = { + data: { somefield: number } | null; + errors: Array | null; + }; + + const baseBlock = de.func({ + block: (): de.DescriptHttpBlockResult => { + return { + statusCode: 200, + headers: {}, + requestOptions: {} as any, + result: { + data: { somefield: 42 }, + errors: null, + }, + }; + }, + options: { + before: () => { + return; + }, + after: ({ result }) => { + return result.result; + }, + }, + }); + + const blockWithUndefined = baseBlock.extend({ + options: { + before: () => { + // eslint-disable-next-line no-constant-condition + if (0 > 0.5) { + return null; + } + }, + after: ({ result }) => { + return result?.data?.somefield; + }, + }, + }); + + // вот тут баг + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const result = await de.run(blockWithUndefined, { + params: {}, + }); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + type Tests = [ + Expect>, + ]; + + expect(result).toEqual(42); + }); }); diff --git a/tests/test.types.ts b/tests/test.types.ts new file mode 100644 index 0000000..54e0a98 --- /dev/null +++ b/tests/test.types.ts @@ -0,0 +1,18 @@ +// https://frontendmasters.com/blog/testing-types-in-typescript/ + +export type Expect = T; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export type Not = true; + +export type ShapesMatch = [T] extends [U] + ? [U] extends [T] + ? true + : false + : false; + +export type TypesMatch = ShapesMatch extends true + ? ShapesMatch extends true + ? true + : false + : false;