diff --git a/integration/batching-with-context-esModuleInterop/batching.ts b/integration/batching-with-context-esModuleInterop/batching.ts index 8264b4efc..eb760ceb5 100644 --- a/integration/batching-with-context-esModuleInterop/batching.ts +++ b/integration/batching-with-context-esModuleInterop/batching.ts @@ -705,7 +705,7 @@ export class EntityServiceClientImpl implements Ent return new DataLoader((ids) => { const request = { ids }; return this.BatchMapQuery(ctx, request).then((res) => { - return ids.map((key) => unwrap(res.entities[key])); + return ids.map((key) => res.entities[key] ?? fail()); }); }, { cacheKeyFn: hash, ...ctx.rpcDataLoaderOptions }); }); @@ -771,9 +771,6 @@ function isSet(value: any): boolean { return value !== null && value !== undefined; } -function unwrap(value: T | undefined | null): T { - if (value === undefined || value === null) { - throw new Error("Expected value to be defined"); - } - return value; +function fail(message?: string): never { + throw new Error(message ?? "Failed"); } diff --git a/integration/batching-with-context/batching.ts b/integration/batching-with-context/batching.ts index d8d1d29b8..319eee661 100644 --- a/integration/batching-with-context/batching.ts +++ b/integration/batching-with-context/batching.ts @@ -705,7 +705,7 @@ export class EntityServiceClientImpl implements Ent return new DataLoader((ids) => { const request = { ids }; return this.BatchMapQuery(ctx, request).then((res) => { - return ids.map((key) => unwrap(res.entities[key])); + return ids.map((key) => res.entities[key] ?? fail()); }); }, { cacheKeyFn: hash, ...ctx.rpcDataLoaderOptions }); }); @@ -771,9 +771,6 @@ function isSet(value: any): boolean { return value !== null && value !== undefined; } -function unwrap(value: T | undefined | null): T { - if (value === undefined || value === null) { - throw new Error("Expected value to be defined"); - } - return value; +function fail(message?: string): never { + throw new Error(message ?? "Failed"); } diff --git a/integration/extensions/test.ts b/integration/extensions/test.ts index 20583ea21..03cf234d9 100644 --- a/integration/extensions/test.ts +++ b/integration/extensions/test.ts @@ -485,7 +485,7 @@ export const bytes: Extension = { return encoded; }, decode: (tag: number, input: Uint8Array[]): Uint8Array => { - const reader = _m0.Reader.create(unwrap(input[input.length - 1])); + const reader = _m0.Reader.create(input[input.length - 1] ?? fail()); return reader.bytes(); }, }; @@ -505,7 +505,7 @@ export const string: Extension = { return encoded; }, decode: (tag: number, input: Uint8Array[]): string => { - const reader = _m0.Reader.create(unwrap(input[input.length - 1])); + const reader = _m0.Reader.create(input[input.length - 1] ?? fail()); return reader.string(); }, }; @@ -525,7 +525,7 @@ export const long: Extension = { return encoded; }, decode: (tag: number, input: Uint8Array[]): Long => { - const reader = _m0.Reader.create(unwrap(input[input.length - 1])); + const reader = _m0.Reader.create(input[input.length - 1] ?? fail()); return reader.int64() as Long; }, }; @@ -545,7 +545,7 @@ export const fixed: Extension = { return encoded; }, decode: (tag: number, input: Uint8Array[]): Long => { - const reader = _m0.Reader.create(unwrap(input[input.length - 1])); + const reader = _m0.Reader.create(input[input.length - 1] ?? fail()); return reader.fixed64() as Long; }, }; @@ -565,7 +565,7 @@ export const enumField: Extension = { return encoded; }, decode: (tag: number, input: Uint8Array[]): Enum => { - const reader = _m0.Reader.create(unwrap(input[input.length - 1])); + const reader = _m0.Reader.create(input[input.length - 1] ?? fail()); return reader.int32() as any; }, }; @@ -583,7 +583,7 @@ export const group: Extension = { return encoded; }, decode: (tag: number, input: Uint8Array[]): Group => { - const reader = _m0.Reader.create(unwrap(input[input.length - 1])); + const reader = _m0.Reader.create(input[input.length - 1] ?? fail()); return Group.decode(reader); }, }; @@ -621,9 +621,6 @@ export interface Extension { packed: boolean; } -function unwrap(value: T | undefined | null): T { - if (value === undefined || value === null) { - throw new Error("Expected value to be defined"); - } - return value; +function fail(message?: string): never { + throw new Error(message ?? "Failed"); } diff --git a/src/generate-services.ts b/src/generate-services.ts index aa9061fcb..2fe599fcf 100644 --- a/src/generate-services.ts +++ b/src/generate-services.ts @@ -259,7 +259,7 @@ function generateBatchingRpcMethod(ctx: Context, batchMethod: BatchMethod): Code // If the return type is a map, lookup each key in the result lambda.push(code` return this.${methodDesc.formattedName}(ctx, request).then(res => { - return ${inputFieldName}.map(key => ${ctx.utils.unwrap}(res.${outputFieldName}[key])) + return ${inputFieldName}.map(key => res.${outputFieldName}[key] ?? ${ctx.utils.fail}()) }); `); } else { diff --git a/src/main.ts b/src/main.ts index f46c5d3b4..a4860b127 100644 --- a/src/main.ts +++ b/src/main.ts @@ -837,19 +837,16 @@ function makeExtensionClass(options: Options) { } function makeAssertionUtils() { - const unwrap = conditionalOutput( - "unwrap", + const fail = conditionalOutput( + "fail", code` - function unwrap(value: T | undefined | null): T { - if (value === undefined || value === null) { - throw new Error('Expected value to be defined'); + function fail(message?: string): never { + throw new Error(message ?? "Failed"); } - return value; - } ` ); - return { unwrap }; + return { fail }; } // Create the interface with properties @@ -1689,7 +1686,7 @@ function generateExtension(ctx: Context, message: DescriptorProto | undefined, e } else { // pick the last entry, since it overrides all previous entries if not repeated chunks.push(code` - const reader = ${Reader}.create(${ctx.utils.unwrap}(input[input.length -1])); + const reader = ${Reader}.create(input[input.length -1] ?? ${ctx.utils.fail}()); return ${readSnippet}; }, `);