Reputation: 13109
Given this interface
from 3rd party library type definitions:
interface IHttpResponse<T> {
data: T;
status: number;
headers: IHttpHeadersGetter;
config: IRequestConfig;
statusText: string;
xhrStatus: 'complete' | 'error' | 'timeout' | 'abort';
}
with IHttpHeadersGetter
being this:
interface IHttpHeadersGetter {
(): { [name: string]: string; };
(headerName: string): string;
}
how can I implement headers
in a class
that implements
IHttpResponse<T>
?
This is what my class
implementation looks like but as one can see, not all members from IHttpHeadersGetter
are implemented:
class MockResponse<T> implements IHttpResponse<T> {
data: T;
status: number;
headers (headerName: string): string {
// return some header value
};
config: IRequestConfig;
statusText: string;
xhrStatus: "complete" | "error" | "timeout" | "abort";
}
Thus, tsc
complains about this:
error TS2345: Argument of type 'MockResponse<any>' is not assignable to parameter of type 'IHttpResponse<any>'.
Types of property 'headers' are incompatible.
Type '(headerName: string) => string' is not assignable to type 'IHttpHeadersGetter'.
How do I have to implement headers
correctly?
Upvotes: 1
Views: 120
Reputation: 38151
The key part is to define both overloads of the headers
function on the class, and then implement the actual method using a type signature that is the two overloads combined.
The final class should be:
class MockResponse<T> implements IHttpResponse<T> {
data: T;
status: number;
// specify the two overloads first
headers(): { [name: string]: string; };
headers(headerName: string): string;
// then implement the method combining both signatures
headers (headerName?: string): string | { [name: string]: string; } {
// return some header value
if (typeof headerName === 'string') {
return headerName;
}
return { some: 'object' };
};
config: IRequestConfig;
statusText: string;
xhrStatus: "complete" | "error" | "timeout" | "abort";
}
See it on typescriptlang.org playground.
Upvotes: 1
Reputation: 330216
The type of IHttpHeadersGetter
has two call signatures. That means it's an overloaded function, and any implementation of it needs to be compatible. The easiest way to do this is to make the implementation itself an overloaded function with the same call signatures as that of IHttpHeadersGetter
.
For example (excluding other properties):
class MockResponse<T> implements IHttpResponse<T> {
// CALL SIGNATURES
headers(): { [name: string]: string }; // call signature 1
headers(headerName: string): string; // call signature 2
// IMPLEMENTATION
headers(headerName?: string): string | { [name: string]: string } {
const theHeaders: { [name: string]: string } = {
someHeader: "hello",
otherHeader: "you"
}
return (typeof headerName !== "string") ? theHeaders :
(headerName in theHeaders) ? theHeaders[headerName] : "";
};
}
This should compile for you and work as desired. Hope that helps; good luck!
Upvotes: 2