Maintaining overridden type definitions for a dependency with TypeScript
Recently, I was struggling with integrating redux-form into a TypeScript project. I hit a couple of bugs in the type definitions for this project, and I went into my node_modules
and fixed them. Of course, as a good open source citizen, I submitted a couple of PRs into the DefinitelyTyped project, but in the meantime, I wanted our team be able to iterate on the project with the fixed type definitions. After a bit of Googling around, I figured it out, but it wasn't super easy to find a working, well-organized and easy-to-maintain solution. So, I decided to write a blog post acting as documentation.
- Create a
typings/
directory somewhere in your project (it doesn't have to be namedtypings
). - Add a directory under
typings/
for each dependency you want to override (e.g.typings/redux-form
). - Copy over the type definitions (all the
.d.ts
files) fromnode_modules
or from DefinitelyTyped into the dependency's directory insidetypings/
. - Edit your
tsconfig.json
and add a path mapping to each dependency like so:
{
...,
"compilerOptions": {
...,
"baseUrl": "src",
"paths": {
"redux-form": ["typings/redux-form"],
"react-monaco-editor": ["typings/react-monaco-editor"],
...
}
}
}
Note that every directory in your paths
object is relative to the baseUrl
property (in our case, we have a src/typings
directory).
If your change to the type definitions is incremental (i.e., you're not editing any type definitions but rather just adding new exported types), you don't have to explicitly add your overriding to compilerOption's paths
. You just have to write declare module "module-name" { ... }
somewhere in your code base and it extend the already-existing type definitions in node_modules
.
The ability to do this is something that I missed from Flow, but I actually prefer TypeScript's more explicit approach. I hope this is useful to someone!