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: overload faast() for specific providers #55

Closed
wants to merge 3 commits into from

Conversation

teppeis
Copy link
Contributor

@teppeis teppeis commented May 16, 2019

Thank you for your awesome library!

I have a problem that an option would be a type error for a particular provider in faast().

An error on faast()

This PR improve this with overloading.

While faastAws and faastGoogle is provided, faast() is more convenient in if conditional branches or switch cases.

@acchou
Copy link
Collaborator

acchou commented May 16, 2019

Thanks for the pull request! I originally had overloads for faast() as well but changed it because api-documenter didn't handle overloads well at the time. Things may have changed though.

To merge this we'll need to make some adjustments:

  • Use api-documenter's overload labelling to distinguish between these overloads

  • update @link tags from other places to specify which overload they point to

  • Also, I wonder if it would be possible to have the return values be more specific, e.g. Promise<AwsFaastModule<M>> for AWS, instead of returning Promise<FaastModule<M>>. This would provide more convenient access to provider-specific options, but we need to see if it breaks anything. In particular, if the provider name is dynamic

  • run npm run build to see the effect on the documentation, build, or API file.

  • run npm run test to verify the testsuite. This will require having both AWS and Google accounts.

If this seems too daunting I'll take it on, just let me know.

@acchou
Copy link
Collaborator

acchou commented May 16, 2019

Also please do a pull before making any of the above changes, as I recently pushed a new version that makes significant changes.

@teppeis
Copy link
Contributor Author

teppeis commented May 16, 2019

@acchou I've rebased, npm run build and improved the return type more specific.
But the document tool does not seem to support "@​label" for overloading yet. (ref. microsoft/rushstack#881)
npm run doc outputs warnings:

Warning: dist/decls/src/faast.d.ts:348:5 - (tsdoc-unsupported-tag) The TSDoc tag "@​label" is not supported by this tool

Also the overloading three signature and the API docs are too heavy.

What about another simple solution just changing the option type to union?

export async function faast<M extends object>(
    provider: Provider,
    fmodule: M,
    options?: AwsOptions | GoogleOptions | LocalOptions
): Promise<FaastModule<M>> {}

@acchou
Copy link
Collaborator

acchou commented May 16, 2019

I've tried that before and it resulted in some type errors in the testsuite, though that was a while ago and the testsuite has evolved. Let me play with this this afternoon and see what happens.

@acchou
Copy link
Collaborator

acchou commented May 17, 2019

The problem with a union type is that it leaves open the possibility of errors such as specifying "aws" as the provider, but giving GoogleOptions that will fail at runtime.

Let's wait until api-documenter supports labels. In the meantime, the current typing for faast() and provider-specific variants is correct, typesafe, and documented cleanly. In the future when api-documenter supports labels for overloads, we can reconsider adding faast() overloads. The provider-specific overloads can continue to be supported without any changes.

In the meantime, consider writing a wrapper function that's pretty much what faast() is except overloaded as you've described. Since this function doesn't need to be documented by faast.js, the api-documenter issue is not a problem. For example:

export async function superfaast<M extends object>(
    provider: "aws",
    fmodule: M,
    options?: AwsOptions
): Promise<AwsFaastModule<M>>;
export async function superfaast<M extends object>(
    provider: "google",
    fmodule: M,
    options?: GoogleOptions
): Promise<GoogleFaastModule<M>>;
export async function superfaast<M extends object>(
    provider: "local",
    fmodule: M,
    options?: LocalOptions
): Promise<LocalFaastModule<M>>;
export async function superfaast<M extends object>(
    provider: Provider,
    fmodule: M,
    options?: CommonOptions
): Promise<FaastModule<M>>;
export async function superfaast<M extends object>(
    provider: Provider,
    fmodule: M,
    options?: CommonOptions
): Promise<FaastModule<M>> {
    switch (provider) {
        case "aws":
            return faastAws(fmodule, options);
        case "google":
            return faastGoogle(fmodule, options);
        case "local":
            return faastLocal(fmodule, options);
        default:
            throw new FaastError(`Unknown cloud provider option '${provider}'`);
    }
}

Or you can use the union type version for simplicity in your own code base, at the cost of possibly having runtime errors (likely caught by testing in practice).

I've found that TypeScript doesn't always give good error message when using overloaded functions like superfaast. For example, if you specify "aws" as the provider, autocomplete will helpfully fill in proper region options for you. But if you specify "google", autocomplete will unhelpfully fill in AWS' regions for you! The type error that results is:

Argument of type '{ region: string; }' is not assignable to parameter of type 'CommonOptions'.

That's not very helpful, and likely to cause confusion. I like the provider-specific faast functions
because they are explicit, always give correct autocomplete, and give clear and correct error messages in all cases. So let's leave them in, and add overloads in the future when TypeScript and api-documenter catch up.

@acchou acchou closed this May 17, 2019
@teppeis teppeis deleted the overload-faast branch May 21, 2019 18:02
@teppeis
Copy link
Contributor Author

teppeis commented May 21, 2019

@acchou Good decision! Thank you for your investigation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants