Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(parser): fix type inference for result types #3293

Merged
merged 8 commits into from
Nov 7, 2024

Conversation

am29d
Copy link
Contributor

@am29d am29d commented Nov 5, 2024

Summary

This PR fixes inferred for result types.

Changes

I have added discriminator field to each envelope to distinguish between array and object return types. We now also have tests to catch any cases where the return type for specific envelope does not match.

Technically the object-envelopes can also return arrays, but this result will be according to the provided schema, i.e. z.array which also matches with current implementation.

Please provide a summary of what's being changed

Please add the issue number below, if no issue is present the PR might get blocked and not be reviewed

Issue number: closes #3226


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.

@am29d am29d requested review from a team as code owners November 5, 2024 20:22
@boring-cyborg boring-cyborg bot added parser This item relates to the Parser Utility tests PRs that add or change tests labels Nov 5, 2024
@pull-request-size pull-request-size bot added the size/L PRs between 100-499 LOC label Nov 5, 2024
@am29d am29d changed the title maintenance(parser): fix type inference for result types chore(parser): fix type inference for result types Nov 6, 2024
Copy link
Contributor

@dreamorosi dreamorosi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the fix, this will improve the experience for customers.

Besides two minor comments on imports within tests, I have noticed that the new symbol property shows up in the IntelliSense autocomplete of the public API:

image

This is not a big deal, but I wonder if we could use alternatives to avoid this. Based on tweets that I read in the past there are at least two options that would avoid this and still serve as discriminator.

The first one is to use a property name that begins with a space, i.e. this:

export const ApiGatewayEnvelope = {
-  'symbol': 'object' as const,
+  ' symbol': 'object' as const,

This works, however according to some sources the fact that it doesn't show might actually be a bug.

The second is to use an actual symbol, for example, in packages/parser/src/envelopes/envelope.ts we could export a symbol like this:

export const envelopeDiscriminator = Symbol.for('returnType');

and then, in each built-in envelope import and use it like this:

- import { Envelope } from './envelope.js';
+ import { Envelope, envelopeDiscriminator } from './envelope.js';

/**
 * API Gateway envelope to extract data within body key
 */
export const ApiGatewayEnvelope = {
-  'symbol': 'object' as const,
+  [envelopeDiscriminator]: 'object' as const,

and same in the packages/parser/src/types/envelope.ts file:

+ import { envelopeDiscriminator } from '../envelopes/envelope.js';

interface ArrayEnvelope {
-  'symbol': 'array';
+  [envelopeDiscriminator]: 'array';
  parse<T extends ZodSchema>(data: unknown, schema: T): z.infer<T>[];
  safeParse<T extends ZodSchema>(
    data: unknown,
    schema: T
  ): ParsedResult<unknown, z.infer<T>[]>;
}

with this method the types still work but the discriminator doesn't show up in the public API:

image

Using a symbol vs a string as key would also, afaik, avoid potential collisions in case customers start adding properties to the envelopes since even if they used the same key the reference would be different (but haven't verified this).

Additionally, I think we could consider & test adding the @internal annotation in the docstring for the object property so that it doesn't show up in the API docs either.

Finally, just as a comment, I think we might have been able to achieve the same result by adding the discriminator only to one group of the envelopes (i.e. the array ones) and then setting the type of the other as never in the interface, so that the absence of the discriminator would have served as discriminator itself. But I actually like being explicit about this, so I'd say let's leave it as-is.

packages/parser/tests/unit/types.test.ts Outdated Show resolved Hide resolved
packages/parser/tests/unit/types.test.ts Outdated Show resolved Hide resolved
am29d and others added 3 commits November 7, 2024 09:26
Co-authored-by: Andrea Amorosi <dreamorosi@gmail.com>
Co-authored-by: Andrea Amorosi <dreamorosi@gmail.com>
@am29d
Copy link
Contributor Author

am29d commented Nov 7, 2024

Thanks for raising this point, I completely forgot about hiding the property.

I have picked your second option, and added @hidden to remove it from our API Docs. I agree on the last point, let's make it explicit.

@am29d am29d requested a review from dreamorosi November 7, 2024 09:24
Copy link

sonarqubecloud bot commented Nov 7, 2024

Copy link
Contributor

@dreamorosi dreamorosi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for addressing the review comments! Great addition

@dreamorosi dreamorosi merged commit 112b4bb into main Nov 7, 2024
23 checks passed
@dreamorosi dreamorosi deleted the 3226/infer-return-type-in-parser branch November 7, 2024 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
parser This item relates to the Parser Utility size/L PRs between 100-499 LOC tests PRs that add or change tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Maintenance: Parser inferred result always set event to array type
2 participants