diff --git a/lib/arrayBlock.ts b/lib/arrayBlock.ts index fb6eacf..898a06f 100644 --- a/lib/arrayBlock.ts +++ b/lib/arrayBlock.ts @@ -79,7 +79,6 @@ class ArrayBlock< > { extend< - // eslint-disable-next-line @typescript-eslint/no-unused-vars ExtendedResultOut extends BlockResultOut, ExtendedParamsOut extends Params = Params, @@ -88,15 +87,20 @@ class ArrayBlock< ExtendedBeforeResultOut = unknown, ExtendedAfterResultOut = unknown, ExtendedErrorResultOut = unknown, + const ExtendedIsRequired extends boolean = IsRequired, >({ options }: { options: DescriptBlockOptions< Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams - >; + > & { required?: ExtendedIsRequired }; }) { - return new ArrayBlock({ + const result = new ArrayBlock({ block: this.extendBlock(this.block), options: this.extendOptions(this.options, options) as typeof options, }); + return result as unknown as ArrayBlock< + Context, Block, ExtendedResultOut, ExtendedParamsOut, ExtendedBlockResult, + ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams, ExtendedIsRequired + >; } protected initBlock(array: ArrayBlockDefinition) { diff --git a/lib/block.ts b/lib/block.ts index b877902..4907f58 100644 --- a/lib/block.ts +++ b/lib/block.ts @@ -78,6 +78,7 @@ abstract class BaseBlock< ExtendedBeforeResultOut = unknown, ExtendedAfterResultOut = unknown, ExtendedErrorResultOut = unknown, + const ExtendedIsRequired extends boolean = IsRequired, >({ block, options }: { block?: CustomBlock; options?: DescriptBlockOptions< @@ -88,7 +89,7 @@ abstract class BaseBlock< ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams - >; + > & { required?: ExtendedIsRequired }; }): unknown; protected initBlock(block: CustomBlock) { diff --git a/lib/firstBlock.ts b/lib/firstBlock.ts index 97a2a83..2e4d046 100644 --- a/lib/firstBlock.ts +++ b/lib/firstBlock.ts @@ -85,7 +85,6 @@ class FirstBlock< > { extend< - // eslint-disable-next-line @typescript-eslint/no-unused-vars ExtendedResultOut extends BlockResultOut, // ExtendedCustomBlock extends FirstBlockDefinition, @@ -95,15 +94,20 @@ class FirstBlock< ExtendedBeforeResultOut = unknown, ExtendedAfterResultOut = unknown, ExtendedErrorResultOut = unknown, + const ExtendedIsRequired extends boolean = IsRequired, >({ options }: { options: DescriptBlockOptions< Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams - >; + > & { required?: ExtendedIsRequired }; }) { - return new FirstBlock({ + const result = new FirstBlock({ block: this.extendBlock(this.block), options: this.extendOptions(this.options, options) as typeof options, }); + return result as unknown as FirstBlock< + Context, Block, ExtendedResultOut, ExtendedParamsOut, ExtendedBlockResult, + ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams, ExtendedIsRequired + >; } protected initBlock(block: FirstBlockDefinition) { diff --git a/lib/httpBlock.ts b/lib/httpBlock.ts index a670fb2..e759ff7 100644 --- a/lib/httpBlock.ts +++ b/lib/httpBlock.ts @@ -214,11 +214,12 @@ class HttpBlock< ExtendedBeforeResultOut = unknown, ExtendedAfterResultOut = unknown, ExtendedErrorResultOut = unknown, + const ExtendedIsRequired extends boolean = IsRequired, >({ options, block }: { block?: DescriptHttpBlockDescription; options?: DescriptBlockOptions< Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams - >; + > & { required?: ExtendedIsRequired }; }) { const x = new HttpBlock< Context, @@ -229,7 +230,8 @@ class HttpBlock< ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, - ExtendedParams + ExtendedParams, + ExtendedIsRequired >({ block: this.extendBlock(block), options: this.extendOptions(this.options, options), diff --git a/lib/objectBlock.ts b/lib/objectBlock.ts index fad2985..2a8d767 100644 --- a/lib/objectBlock.ts +++ b/lib/objectBlock.ts @@ -110,7 +110,6 @@ class ObjectBlock< } extend< - // eslint-disable-next-line @typescript-eslint/no-unused-vars ExtendedResultOut extends BlockResultOut, // ExtendedCustomBlock extends ObjectBlockDefinition, @@ -120,15 +119,20 @@ class ObjectBlock< ExtendedBeforeResultOut = unknown, ExtendedAfterResultOut = unknown, ExtendedErrorResultOut = unknown, + const ExtendedIsRequired extends boolean = IsRequired, >({ options }: { options: DescriptBlockOptions< Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams - >; + > & { required?: ExtendedIsRequired }; }) { - return new ObjectBlock({ + const result = new ObjectBlock({ block: this.extendBlock(this.block), options: this.extendOptions(this.options, options) as typeof options, }); + return result as unknown as ObjectBlock< + Context, Blocks, ExtendedResultOut, ExtendedParamsOut, ExtendedBlockResult, + ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams, ExtendedIsRequired + >; } } diff --git a/lib/pipeBlock.ts b/lib/pipeBlock.ts index def6553..992d03b 100644 --- a/lib/pipeBlock.ts +++ b/lib/pipeBlock.ts @@ -78,9 +78,8 @@ class PipeBlock< > { extend< - // eslint-disable-next-line @typescript-eslint/no-unused-vars - // ExtendedResultOut extends - // BlockResultOut, + ExtendedResultOut extends + BlockResultOut, // ExtendedCustomBlock extends PipeBlockDefinition, ExtendedParamsOut extends Params = Params, ExtendedParams = Params, @@ -88,15 +87,20 @@ class PipeBlock< ExtendedBeforeResultOut = unknown, ExtendedAfterResultOut = unknown, ExtendedErrorResultOut = unknown, + const ExtendedIsRequired extends boolean = IsRequired, >({ options }: { options: DescriptBlockOptions< Context, ExtendedParamsOut, ExtendedBlockResult, ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams - >; + > & { required?: ExtendedIsRequired }; }) { - return new PipeBlock({ + const result = new PipeBlock({ block: this.extendBlock(this.block), options: this.extendOptions(this.options, options) as typeof options, }); + return result as unknown as PipeBlock< + Context, Block, ExtendedResultOut, ExtendedParamsOut, ExtendedBlockResult, + ExtendedBeforeResultOut, ExtendedAfterResultOut, ExtendedErrorResultOut, ExtendedParams, ExtendedIsRequired + >; } protected initBlock(block: PipeBlockDefinition) { diff --git a/tests/options.required.test.ts b/tests/options.required.test.ts index de1ae2e..0be0d63 100644 --- a/tests/options.required.test.ts +++ b/tests/options.required.test.ts @@ -232,4 +232,170 @@ describe('options.required', () => { Expect>, ]; }); + + it('types: func .extend({ required: true }) removes DescriptError from object block result', async() => { + const base = de.func({ + block: () => 42, + }); + const block = de.object({ + block: { + foo: base.extend({ + options: { + required: true, + }, + }), + }, + }); + + const result = await de.run(block, { params: {} }); + + expect(result.foo).toBe(42); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + type Tests = [ + Expect>, + ]; + }); + + it('types: http .extend({ required: true }) removes DescriptError from object block result', async() => { + const path = getPath(); + fake.add(path, { + statusCode: 200, + headers: { 'content-type': 'application/json' }, + content: JSON.stringify({ foo: 'bar' }), + }); + + const base = de.http({ + block: { + hostname: 'localhost', + port: PORT, + pathname: path, + }, + options: { + after: ({ result }) => result.result as { foo: string }, + }, + }); + const block = de.object({ + block: { + data: base.extend({ + options: { + required: true, + }, + }), + }, + }); + + const result = await de.run(block); + + expect(result.data).toEqual({ foo: 'bar' }); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + type Tests = [ + Expect>, + ]; + }); + + it('types: http .extend({ required: false }) keeps DescriptError in object block result', async() => { + const path = getPath(); + fake.add(path, { + statusCode: 200, + headers: { 'content-type': 'application/json' }, + content: JSON.stringify({ foo: 'bar' }), + }); + + const base = de.http({ + block: { + hostname: 'localhost', + port: PORT, + pathname: path, + }, + options: { + after: ({ result }) => result.result as { foo: string }, + }, + }); + const block = de.object({ + block: { + data: base.extend({ + options: { + required: false, + }, + }), + }, + }); + + const result = await de.run(block); + + expect(result.data).toEqual({ foo: 'bar' }); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + type Tests = [ + Expect>, + ]; + }); + + it('types: http .extend() inherits required=true from parent', async() => { + const path = getPath(); + fake.add(path, { + statusCode: 200, + headers: { 'content-type': 'application/json' }, + content: JSON.stringify({ foo: 'bar' }), + }); + + const base = de.http({ + block: { + hostname: 'localhost', + port: PORT, + pathname: path, + }, + options: { + after: ({ result }) => result.result as { foo: string }, + required: true, + }, + }); + const block = de.object({ + block: { + data: base.extend({}), + }, + }); + + const result = await de.run(block); + + expect(result.data).toEqual({ foo: 'bar' }); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + type Tests = [ + Expect>, + ]; + }); + + it('types: object .extend({ required: true }) removes DescriptError from parent object block result', async() => { + const inner = de.object({ + block: { + foo: de.func({ + block: () => 42, + options: { + required: true, + }, + }), + }, + }); + const block = de.object({ + block: { + data: inner.extend({ + options: { + required: true, + }, + }), + }, + }); + + const result = await de.run(block, { params: {} }); + + expect(result.data).toEqual({ foo: 42 }); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + type Tests = [ + Expect>, + ]; + }); });