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
[node] Update older node types (7,6,4) for more consistency with 8 #20695
Conversation
* Specifically add interfaces for reqeust headers * Make the naming of client request options consistent (ClientRequestArgs)
types/node/v4/index.d.ts to authors (@DefinitelyTyped/DefinitelyTyped Microsoft TypeScript (account can't be detected)). Could you review this PR? types/node/v6/index.d.ts to authors (@DefinitelyTyped/DefinitelyTyped @WilcoBakker @inlined Microsoft TypeScript (account can't be detected)). Could you review this PR? 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? |
Approved by a listed owner. PR ready to merge pending express review by a maintainer. |
Can try to review this tomorrow. |
There was a problem hiding this 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)
@kevin-greene-ck Please fix the failures indicated in the Travis CI log. |
@inlined - Thanks for your review of this PR! Can you please look at the new code and update your review status if appropriate? |
There was a problem hiding this 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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification.
types/node/v4/index.d.ts
Outdated
@@ -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[]; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
types/node/v4/index.d.ts
Outdated
export type IncomingHttpHeaders = { | ||
[header: string]: string | ||
} & { | ||
'set-cookie'?: string[] | ||
} |
There was a problem hiding this comment.
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),
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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' ]
};
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
types/node/v4/index.d.ts
Outdated
} | ||
|
||
// outgoing headers allows numbers (as they are converted internally to strings) | ||
export interface OutgoingHttpHeaders { | ||
[header: string]: number | string | string[] | undefined; | ||
export type OutgoingHttpHeaders = { |
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
@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. |
@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. |
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. |
@kevin-greene-ck Please fix the failures indicated in the Travis CI log. |
@RyanCavanaugh Everything is fixed, but travis times out. |
Please fill in this template.
npm run lint package-name
(ortsc
if notslint.json
is present).Select one of these and delete the others:
If changing an existing definition:
tslint.json
containing{ "extends": "dtslint/dt.json" }
.