27
loading...
This website collects cookies to deliver better user experience
http.IncomingMessage
) from my usershttp.IncomingHttpHeaders
).http.IncomingHttpHeaders
interface:interface IncomingHttpHeaders {
'accept-patch'?: string;
'accept-ranges'?: string;
'accept'?: string;
…
'warning'?: string;
'www-authenticate'?: string;
[header: string]: string | string[] | undefined;
}
Context
and I hand out instances of that to handlers for each request:export class Context {
constructor(private req: http.IncomingMessage) { }
…
getHeader(name: ?) {
return req.headers[name];
}
}
…
?
so that it allows only those headers from http.IncomingHttpHeaders
that are hard-coded, we will call them “known keys”.type StandardHeaders = keyof http.IncomingHtppHeaders
because the interface has index signature, that resolves into StandardHeaders
accepting anything so auto-completion and compile-time checking doesn’t work.type StandardHeaders = {
// copy every declared property from http.IncomingHttpHeaders
// but remove index signatures
[K in keyof http.IncomingHttpHeaders as string extends K
? never
: number extends K
? never
: K]: http.IncomingHttpHeaders[K];
};
http.IncomingHttpHeaders
with index signatures removed.‘a’ extends string
is true
but string extends ’a’
is false
. Same for number
.type StandardHeader = keyof StandardHeaders;
StandardHeader
:getHeader(name: StandardHeader)
and try to use it:Context
generic and add several things:export class Context<TCustomHeader extends string = StandardHeader> {
constructor(private req: http.IncomingMessage) { }
…
getHeader(name: StandardHeader | TCustomHeader) {
return req.headers[name];
}
…
}
const ctx = new Context<'X-Foo' | 'X-Bar'>(...);
const foo = ctx.getHeader('X-Foo');
const bar = ctx.getHeader('X-Bar');
Context
class themselves, we’re handing those out. So instead we should introduce a class ContextHeaders
and replace getHeader(header: StandardHeader)
with generic method headers< TCustomHeader extends string = StandardHeader>: ContextHeaders<StandardHeader | TCustomHeader>