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: enhance client-related typings #1227

Merged
merged 3 commits into from
Jan 12, 2021

Conversation

kyle221b
Copy link
Contributor

@kyle221b kyle221b commented Dec 5, 2020

Fixes

The MailService has a method to set a client, but it isn't exposed in typings. Adding this so there is an easier way to customize underlying agents used (for keep-alive and other connection-pooling settings) without having compilation problems (or subverting the type system by just using 'any')

Checklist

  • I acknowledge that all my contributions will be made under the project's license
  • I have made a material change to the repo (functionality, testing, spelling, grammar)
  • I have read the Contribution Guidelines and my PR follows them
  • I have titled the PR appropriately
  • I have updated my branch with the main branch
  • I have added tests that prove my fix is effective or that my feature works
  • I have added the necessary documentation about the functionality in the appropriate .md file
  • I have added inline documentation to the code I modified

If you have questions, please file a support ticket, or create a GitHub Issue in this repository.

The MailService has a method to set a client, but it isn't exposed in
typings. Adding this so there is an easier way to customize underlying
agents used (for keep-alive and other connection-pooling settings)
without having compilation problems (or subverting the type system by
just using 'any')
@thinkingserious thinkingserious added the status: code review request requesting a community code review or review from Twilio label Dec 5, 2020
@@ -46,5 +46,8 @@ declare class Client {
request(data: ClientRequest, cb?: (err: ResponseError, response: [ClientResponse, any]) => void): Promise<[ClientResponse, any]>;
}

declare const client: Client & { Client: typeof Client };
declare const client: Client;
// @ts-ignore
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This matches style of mail.d.ts file. Part that I wanted to change here mainly was the { Client: typeof Client } piece. I get the feeling that the goal there was to expose the class as a type, but we do typeof on the class itself, instead of an instance of it, so it ends up being a type with just a prototype field. Let me know if I'm missing something here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this change might break folks: #986

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah the goal here was to export Client as not just a value with type typeof Client, but to export the class itself, which could be used as a value or a type. im pretty sure this will only enhance the existing functionality. currently, users could do:
const a = new Client()

but the only way they could pass the actual type around is by doing a default import of the singleton client and then doing a typeof on it.

am i missing something here?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't quite understand why this method is better than what we have. Perhaps a good way to illustrate is to add a sample quick start here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To give a quick code example:

import { Client } from '@sendgrid/client';

// This is possible in both versions
const client = new Client();

// This (I think) is only possible in the new version since Client is only a value in the old version and not a type
function somethingThatTakesInAClient(client: Client) {
...
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

while it isn't necessary, you do it for most of your other types that I've seen, and if you are going to export functionality, it seems to me it would also make sense to export the type

Copy link
Contributor Author

@kyle221b kyle221b Dec 18, 2020

Choose a reason for hiding this comment

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

to further illustrate, in the existing code, we could accomplish the same by doing:

// Note we are importing the singleton client exported by the lib as well as the class itself (as a value)
import client, { Client } from '@sendgrid/client';

// We can do a typeof on the singleton instance. This is equivalent to what is in the last example. For this one you need // to import a singleton instance of the client just to get the type
function somethingThatTakesInAClient(arg: typeof client) {
...
}

// This compiles, but the behavior isn't what you expect. Since we are doing typeof on the class, the only members are // things on the function prototype, so we can't access methods like 'setApiKey' for example
function anotherThingThatLooksLikeItTakesInAClientButDoesntReally(arg: typeof Client) {
...
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kyle221b
Copy link
Contributor Author

@thinkingserious any chance you or someone from your team could take a look at this?

@thinkingserious thinkingserious added the type: community enhancement feature request not on Twilio's roadmap label Dec 14, 2020
Copy link
Contributor

@thinkingserious thinkingserious 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 PR @kyle221b!

@@ -46,5 +46,8 @@ declare class Client {
request(data: ClientRequest, cb?: (err: ResponseError, response: [ClientResponse, any]) => void): Promise<[ClientResponse, any]>;
}

declare const client: Client & { Client: typeof Client };
declare const client: Client;
// @ts-ignore
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this change might break folks: #986

export = client

export {Client};
Copy link
Contributor

Choose a reason for hiding this comment

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

We would need to revert this change also if we move back to declare const client: Client & { Client: typeof Client };

Copy link
Contributor Author

Choose a reason for hiding this comment

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

left a comment above about why I did this. let me know what you think

@@ -7,4 +9,5 @@ export default interface RequestOptions<TData = any, TParams = object> {
qs?: TParams;
body?: TData;
headers?: object;
httpsAgent?: https.Agent;
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this data is stored in headers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is a top-level field on an axios request. i don't think we'd want to pass it in headers b/c it won't actually get sent across the wire, it's just connection settings essentially.

if we were to add it to headers, then there would need to be a code change in the JS file to filter it out and pass it as a top-level field in the axios request

@thinkingserious
Copy link
Contributor

@kyle221b,

Your reasoning on this thread makes sense to me. However, I'm still concerned about the points made in this PR.

@danhlee329, @dfcowell, @manusis, @mgummelt -- do you have any thoughts on this issue? Thanks!

With best regards,

Elmer

@kyle221b
Copy link
Contributor Author

Anybody have thoughts on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: code review request requesting a community code review or review from Twilio type: community enhancement feature request not on Twilio's roadmap
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants