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

fix(types): add explicit return type to webhooks() function #201

Merged
merged 4 commits into from
Feb 17, 2021

Conversation

oscard0m
Copy link
Member

@oscard0m oscard0m commented Feb 8, 2021

Fix #200

@ghost ghost added this to Inbox in JS Feb 8, 2021
@oscard0m oscard0m requested a review from G-Rath February 8, 2021 22:37
@ghost ghost moved this from Inbox to Bugs in JS Feb 8, 2021
@oscard0m
Copy link
Member Author

oscard0m commented Feb 8, 2021

@G-Rath tried some combinations with Generics and I'm not able to make the tests pass. In all of them the octokit expected prop fails. Probably I'm missing something with TS.

Feel free to modify this PR and merge when working. I have to go to sleep now.

@oscard0m
Copy link
Member Author

oscard0m commented Feb 8, 2021

Maybe @wolfy1339 has some TS magic to share here? 😄

@wolfy1339
Copy link
Member

Maybe @wolfy1339 has some TS magic to share here? smile

Sorry. I haven't really looked into this.

@gr2m
Copy link
Contributor

gr2m commented Feb 9, 2021

Thanks @oscard0m!

I think this fails because the return value is not Webhooks, but Webhooks with a custom TTransformed

@gr2m gr2m force-pushed the add-return-type-to-webhooks-function branch from 49bb981 to c18b94f Compare February 9, 2021 15:31
src/webhooks.ts Outdated

import { Options } from "./types";

export function webhooks(
appOctokit: Octokit,
options: Required<Options>["webhooks"]
) {
): Webhooks<EmitterWebhookEvent, EmitterWebhookEvent & { octokit: Octokit }> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I was hoping that we won't need to set the Type parameters anymore with v8 😕

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice. I was trying to make it compile in my local but I was missing this second generic argument part.


I would like to find a way to let TypeScript auto-infer the type yes... @G-Rath do you think it would be possible (in a different PR) to get this BaseWebhookEvent inference properly solved?

Copy link
Member

Choose a reason for hiding this comment

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

The solution would be to export BaseWebhookEvent, which in itself might not be the worst idea but for this specific case is: the resulting type will be every possible element of the union, which is huge.

Instead, providing the type explicitly is the better solution, as it's for a public export - relying on inference means it'd be possible for the types to subtly change without knowing (even via say a package update if we were to change the types upstream).

Copy link
Contributor

Choose a reason for hiding this comment

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

relying on inference means it'd be possible for the types to subtly change without knowing (even via say a package update if we were to change the types upstream).

that would also include fixes though, right?

providing the type explicitly is the better solution

as it is right now in this PR? Or would you change anything?

Copy link
Member

Choose a reason for hiding this comment

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

that would also include fixes though, right?

Yes, but actually you'll never get fixes, as I just realised this'll never actually be inferred: type definitions have to be explicitly typed in full, as they don't have the source code which is required for TypeScript to infer the code.

i.e

export const fn = () => 'hello world!';

will always give you:

export const fn: () => string;

So for any "fixes" we'd always have to publish a new version for the type definitions to include them.
If we rely on inference, we won't know that the types need to be updated, since it won't cause an error.

Copy link
Member

@G-Rath G-Rath Feb 15, 2021

Choose a reason for hiding this comment

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

as it is right now in this PR? Or would you change anything?

It looks good to me as is. I suspect it'll need changing when octokit/webhooks.js#464 is merged

@oscard0m oscard0m requested review from gr2m, G-Rath and wolfy1339 and removed request for G-Rath and wolfy1339 February 15, 2021 12:57
@gr2m gr2m force-pushed the add-return-type-to-webhooks-function branch from 6bd83cf to 54c072a Compare February 17, 2021 01:19
@gr2m gr2m self-assigned this Feb 17, 2021
@ghost ghost moved this from Bugs to In progress in JS Feb 17, 2021
@gr2m gr2m merged commit 460bf2e into master Feb 17, 2021
JS automation moved this from In progress to Done Feb 17, 2021
@gr2m gr2m deleted the add-return-type-to-webhooks-function branch February 17, 2021 01:25
@github-actions
Copy link

🎉 This PR is included in version 10.1.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@gr2m
Copy link
Contributor

gr2m commented Feb 17, 2021

It looks like with the latest changes of @octokit/webhooks we no longer need to set the return type explicitly, and I don't think there are any performance regressions from the type inference @G-Rath

The typescript definitions build with @pika/pack for the published package look like this

// pkg/dist-types/webhooks.d.ts
import { Octokit } from "@octokit/core";
import { Webhooks } from "@octokit/webhooks";
import { Options } from "./types";
export declare function webhooks(appOctokit: Octokit, options: Required<Options>["webhooks"]): Webhooks<{
    octokit: Octokit;
    id: string;
    name: "push";
    payload: import("@octokit/webhooks-definitions/schema").PushEvent;
} | {
    octokit: Octokit;
    id: string;
    name: "public";
    payload: import("@octokit/webhooks-definitions/schema").PublicEvent;
} | {
// ... many more events here
} | {
    octokit: Octokit;
    id: string;
    name: "workflow_run";
    payload: import("@octokit/webhooks-definitions/schema").WorkflowRunEvent;
}>;

Compared to the current

import { Octokit } from "@octokit/core";
import { Webhooks, EmitterWebhookEvent } from "@octokit/webhooks";
import { Options } from "./types";
export declare function webhooks(appOctokit: Octokit, options: Required<Options>["webhooks"]): Webhooks<EmitterWebhookEvent & {
    octokit: Octokit;
}>;

I guess in the end it's the same thing? Or do you think that the big union will be a significant performance impact, and I just don't see it on my machine?

@G-Rath
Copy link
Member

G-Rath commented Feb 18, 2021

do you think that the big union will be a significant performance impact, and I just don't see it on my machine?

I don't see it as a massive performance problem, but it'll likely make the types harder to work with - I'd expect error messages to be something like "type does not match x, y, ... 20 others, z" instead of "type does not match Webhooks", and wouldn't be surprised if it caused some loss of quality for IDEs as they tend to provide different autocompletion and coloring based on if a type is a union or not (plus they have to resolve the properties in the sum of the union).

It also bloats the package out unnecessarily, and like I said earlier if the types change in a way that would be breaking, we'd not actually know meaning there's a higher risk of disrupting downstream consumers.

On the flip side it also means if we change our transformation we won't be told if the type output changes.

These are all edge cases in their own right, but imo its not worth saving us a couple of characters in our source code given the likely hood it'd need changing.

@gr2m
Copy link
Contributor

gr2m commented Feb 18, 2021

These are all edge cases in their own right, but imo its not worth saving us a couple of characters in our source code given the likely hood it'd need changing.

Agreed, thank you for the clarifications. I'll add a reference to this PR for future reference on why we added an explicit return type in #204

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
JS
  
Done
4 participants