To augment hapi
module to add type checking for server methods, following is the code:
import { Server } from 'hapi';
declare module 'hapi' {
export interface Server {
methods: {
getUsername: () => Promise<string>;
};
}
}
However, this doesn't work because @types/hapi
package already defines methods
as:
readonly methods: Util.Dictionary<ServerMethod>;
From this StackOverflow question, As far as I know, it is not possible to redefine the existing property. But I am not sure. I could not find any documentation about this. If this is not the case, how can I augment/patch/fix the type info?
As a workaround, I have created a new Hapi.js Server interface that extends the original interface. So instead of using hapi Server
interface, I am using the one I created:
// src/augment.d.ts
import { Server as HapiServer } from 'hapi';
export interface Server extends HapiServer {
methods: {
getUsername: () => Promise<string>;
};
}
// In my file src/server.ts file
import { Server } from 'src/augment';
// NOW IT TYPECHECKS CORRECTLY
const username = server.methods.getUsername();
Is this the right approach to take?
While we can't modify the type of an existing field in an interface, we can modify the type of the field in this case. The type of the field is Util.Dictionary<ServerMethod>
. While Util.Dictionary
is used in several places, the only place it is used with the type argument ServerMethod
is for this member.
We can extend the Dictionary
interface with the extra methods and have the methods only show up if the type parameter is ServerMethod
(also we do a bit of magic insipider from here to not show the methods if T
is any
)
declare module 'hapi' {
export namespace Util {
type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N;
export interface Dictionary<T> {
getUsername<T extends ServerMethod>(this: Dictionary<T> & IfAny<T, never, {}>) : Promise<string>;
}
}
}
let d = new Server({})
let f!: Util.Dictionary<any>;
d.methods.getUsername() // type checked
Note
Ideally there would be a dedicated type for methods
that would allow us to add methods to it without extending the very generic Dictionary
interface, but the typings are what they are right now. Someone could do a pull request to create a new interface for methods
....