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

[node] Update older node types (7,6,4) for more consistency with 8 #20695

Merged
merged 16 commits into from Nov 14, 2017

Conversation

kevin-greene-ck
Copy link
Contributor

  • Specifically add interfaces for reqeust headers
  • Make the naming of client request options consistent (ClientRequestArgs)

Please fill in this template.

  • Use a meaningful title for the pull request. Include the name of the package modified.
  • Test the change in your own code. (Compile and run.)
  • Follow the advice from the readme.
  • Avoid common mistakes.
  • Run npm run lint package-name (or tsc if no tslint.json is present).

Select one of these and delete the others:

If changing an existing definition:

  • Provide a URL to documentation or source code which provides context for the suggested changes: [thrift] Remove dependency on node v8 #20579
  • Increase the version number in the header if appropriate.
  • If you are making substantial changes, consider adding a tslint.json containing { "extends": "dtslint/dt.json" }.

  * Specifically add interfaces for reqeust headers
  * Make the naming of client request options consistent (ClientRequestArgs)
@dt-bot
Copy link
Member

dt-bot commented Oct 18, 2017

types/node/v4/index.d.ts

to authors (@DefinitelyTyped/DefinitelyTyped Microsoft TypeScript (account can't be detected)). Could you review this PR?
👍 or 👎?


types/node/v6/index.d.ts

to authors (@DefinitelyTyped/DefinitelyTyped @WilcoBakker @inlined Microsoft TypeScript (account can't be detected)). Could you review this PR?
👍 or 👎?


types/node/v7/index.d.ts

to authors (@DefinitelyTyped/DefinitelyTyped @parambirs @robdesideri @tellnes @WilcoBakker Microsoft TypeScript (account can't be detected)). Could you review this PR?
👍 or 👎?

@typescript-bot typescript-bot added the Popular package This PR affects a popular package (as counted by NPM download counts). label Oct 18, 2017
@typescript-bot typescript-bot added the Unmerged The author did not merge the PR when it was ready. label Oct 23, 2017
@typescript-bot
Copy link
Contributor

typescript-bot commented Oct 23, 2017

Approved by a listed owner. PR ready to merge pending express review by a maintainer.

@inlined
Copy link
Contributor

inlined commented Oct 23, 2017

Can try to review this tomorrow.

Copy link
Contributor

@inlined inlined left a comment

Choose a reason for hiding this comment

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

I'll need some time to do a deeper review on the actual conformance to the docs of each version, but there is a high-level issue:

This PR renames a type in the http package (though oddly it does not rename the corresponding type in the https package). Since this code is in active use for developers it will be considered a breaking change.

I personally don't mind adding definitions to what previously was an any but renaming RequestOptions to ClientRequestArgs seems to go too far. We should either drop that part of the change or add a type alias for existing code (I would love other reviewers to chime in)

@typescript-bot typescript-bot removed this from Merge: YSYL in Pull Request Triage Backlog Oct 23, 2017
@typescript-bot
Copy link
Contributor

typescript-bot commented Oct 23, 2017

@kevin-greene-ck Please fix the failures indicated in the Travis CI log.

@typescript-bot typescript-bot added The Travis CI build failed and removed Unmerged The author did not merge the PR when it was ready. labels Oct 23, 2017
@sheetalkamat sheetalkamat added Revision needed This PR needs code changes before it can be merged. and removed Awaiting reviewer feedback labels Oct 23, 2017
@typescript-bot typescript-bot removed the Revision needed This PR needs code changes before it can be merged. label Oct 24, 2017
@typescript-bot
Copy link
Contributor

@inlined - Thanks for your review of this PR! Can you please look at the new code and update your review status if appropriate?

Copy link
Contributor

@inlined inlined left a comment

Choose a reason for hiding this comment

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

Thanks for the patience and the contribution. Just a few nits. I'd prefer to use a slightly more obscure type that's more technically correct since Node only returns an array of string for a single header name.


// outgoing headers allows numbers (as they are converted internally to strings)
export interface OutgoingHttpHeaders {
[header: string]: number | string | string[] | undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

I could not find a reference to undefined. What is the behavior 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.

Yeah, this probably shouldn't be included. It doesn't blow things up. But it does put the string literal 'undefined' as the header value. I removed it.

Copy link
Contributor

Choose a reason for hiding this comment

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

The reason for adding undefined here is to allow users to augment the interface like this to get code completion for often used headers:

interface OutgoingHttpHeaders  {
  age?: string;
  host?: string;
}

if | undefined is not added in the index signature it's only possible to add mandatory properties which is useless.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the clarification.

@@ -565,21 +557,34 @@ declare module "http" {
import * as net from "net";
import * as stream from "stream";

// incoming headers will never contain number
export interface IncomingHttpHeaders {
[header: string]: string | string[];
Copy link
Contributor

Choose a reason for hiding this comment

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

https://nodejs.org/docs/latest-v4.x/api/http.html#http_message_headers says that the only header that will be an array of string is set-cookie and that it will always be an array of string. This admittedly took me a long time to figure out but:

export type HTTPHeader = {
  [header: string]: string
} & {
  'set-cookie'?: string[]
}

enforces that constraint

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch.

@@ -637,21 +629,34 @@ declare module "http" {
import * as net from "net";
import * as stream from "stream";

// incoming headers will never contain number
export interface IncomingHttpHeaders {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as v4

@@ -654,22 +646,34 @@ declare module "http" {
import * as net from "net";
import * as stream from "stream";

// incoming headers will never contain number
export interface IncomingHttpHeaders {
Copy link
Contributor

Choose a reason for hiding this comment

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

And same two comments here again too.

@typescript-bot typescript-bot added the Revision needed This PR needs code changes before it can be merged. label Oct 27, 2017
@typescript-bot typescript-bot removed the Revision needed This PR needs code changes before it can be merged. label Oct 27, 2017
export type IncomingHttpHeaders = {
[header: string]: string
} & {
'set-cookie'?: string[]
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please split this into two interfaces and and combine them to a type then to allow augmentation. Additionally it would be nice if this could be also added to Node 8 (as the main target here is anyway to sync them),

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 on the fence about this honestly. The type names are pretty useless (e.g. we wouldn't expect a docs page on them by themselves) and I've seen IDEs do a worse job at code complete or mouseover docs once the subtypes in a composite type are named.

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 actually doesn't work. I was adding tests for this and I get the same "Property ''set-cookie'' is incompatible with index signature." I would expect if I added the set cookie property onto IncomingHttpHeaders like this

type IncomingHttpHeaders {
    [header: string]: string;
    'set-cookie'?: string[];
}

For this to work the index signature must account for string | string[]. Is there any reason to still use an Intersection type?

Copy link
Contributor

Choose a reason for hiding this comment

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

Don't ask me why, but

type IncomingHttpHeaders {
    [header: string]: string;
    'set-cookie'?: string[];
}

is a compiler error while

type IncomingHttpHeaders {
    [header: string]: string;
} & {
    'set-cookie'?: string[];
}

is not. Types do not allow properties to have a different value type as the index value type, but you can get around this with composite types. Verified the type definition and variable instantiation compile cleanly on TS 5.3.0.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The type definition compiles in the second example, but usage of the type does not. That's why I didn't catch it until I was adding tests for it.

At least this test doesn't compile with typescrpt@2.5.3

const headers: http.IncomingHttpHeaders = {
            'Content-Type': 'application/json',
            'set-cookie': [ 'type=ninja', 'language=javascript' ]
};

Copy link
Contributor

@Flarna Flarna Oct 27, 2017

Choose a reason for hiding this comment

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

What a pity. As we have to include the array in the index signature anyway I see no reason for having two types. To get the best out of it we could add other header names besides set-cookie to force them to string. Users can add more by augmenting the interface for their private header names. e.a.:

interface IncomingHttpHeaders extends Partial<Record<"age" | "host" | "date", string>> {
    'set-cookie'?: string[];
    [name: string]: string | string[] | undefined;
}

Or using copy/paste instead Partial<Record<>> which is maybe easier to read:

interface IncomingHttpHeaders {
    age?: string;
    host?: string;
    //...
    'set-cookie'?: string[];
    [name: string]: string | string[] | undefined;
}

Again the | undefined is needed here to allow adding optional properties.

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 list of common headers isn't too long I can add those to string and users can extend.

}

// outgoing headers allows numbers (as they are converted internally to strings)
export interface OutgoingHttpHeaders {
[header: string]: number | string | string[] | undefined;
export type OutgoingHttpHeaders = {
Copy link
Contributor

Choose a reason for hiding this comment

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

All outgoing headers can be specified as array by user, not just set-cookie. This differs from incoming headers where node combines them during parsing.

Copy link
Contributor

@inlined inlined left a comment

Choose a reason for hiding this comment

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

My comments are incorporated and I'm going to be AFK for a while. Passing the baton to @Flarna who had some good comments. Please come to an agreement on whether the composite type should be built on anonymous or named types before checking in.

@typescript-bot typescript-bot added the Other Approved This PR was reviewed and signed-off by a community member. label Oct 27, 2017
@kevin-greene-ck
Copy link
Contributor Author

@sheetalkamat After resolving merge conflict travis is trying to run tests on all packages instead of just my changes. Is there something I can do about this? Testing the node package works locally.

@Flarna
Copy link
Contributor

Flarna commented Oct 27, 2017

@kevin-greene-ck I'm sorry but I think the root cause here is my request to sync back to node 8. >1000 modules depend on latest node and therefore all of them are tested and this often results in unrelated fails.

@kevin-greene-ck
Copy link
Contributor Author

Ah yes, I guess that merge commit was the first time travis ran after I made changes to node 8. Hmm. Thanks for the insight.

@RyanCavanaugh
Copy link
Member

@kevin-greene-ck Please fix the failures indicated in the Travis CI log.

@kevin-greene-ck
Copy link
Contributor Author

@RyanCavanaugh Everything is fixed, but travis times out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Other Approved This PR was reviewed and signed-off by a community member. Popular package This PR affects a popular package (as counted by NPM download counts).
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants