I’ve been working with Typescript on a daily basis for the last year.
Admittedly, I still feel pretty amateurish with it. Mostly due to the fact that
I’ve mostly been working with it on an existing stack at work and minor
application of it on my own side projects.
With a new side project landing on my TODO list recently, I figured it’d be a
great time to really immerse myself. The stack is your typical *ERN deal,
probably using Redis instead of MongoDB as the primary data store, and
ts
ing the hell out of the whole damn thing.
And so it began, the usual anxiety of starting a brand new project from the
ground up. The canvas was blank, and I had to get my research on.
Most of it’s all come together pretty well thus far, and the bigger plan here is
to build myself a nice little boilerplate that I can use on future endeavors,
that fits into how I build systems.
The big issue that really stopped me in my tracks last week was dealing with a
couple of dependencies that lacked @types
and I had to define on my own
declarations for.
The error initially cropped up as a lint error in nvim
(by way of ALE
). It
said I needed to try installing the @type
for the packages and if that didn’t
work, slap declare module 'package';
in the project.
Not a ton of indication as to where that should have been placed, so I dropped
it into index.d.ts
in the root of the problem. My linter picked up and
everything was good to go.
That was, until I went to run things with ts-node
. Everything actually worked
fine with ts-node-dev
, which I was planning to use, but I really wanted to
figure out why ts-node
wasn’t having it.
After a ton of research and trying a ton of different things (different file
names, configuring stuff in tsconfig.json
, et cetera), I was still dead in the
water. Fortunately, the official Typescript documentation is pretty solid and I
read up on how you’re supposed to declare modules.
The line of code to declare a module was sufficient enough, but just stuffing
shit into index.d.ts
(or nearly any other *.d.ts
for that matter) wasn’t
going to cut it.
To get ts-node
to be back on Team Josh, I ended up creating a types
directory, and a directory named after each dependency I was attempting to
declare.
Within each directory, I added an index.d.ts
and added the aforementioned
declaration line. Things looked something like this:
$ tree types
types
└── package
└── index.d.ts
1 directory, 1 file
$ cat types/package/index.d.ts
declare module 'package'
Hoping this would be enough for a modern version of Typescript, I tried to run
my code again, and hit the same error.
Next step in the process was to configure typeRoots
in my tsconfig.json
file. I had read some mixed statements about this, so not entirely sure if it
was the best approach, but seemed to be the best way to ensure I didn’t have to
tweak the configuration every time I needed to add something new to my local
types
directory.
The thing with the typeRoots
directive is that it’s all or nothing. It’s not
like you can define your custom location and it’s loaded in additional to the
defaults.
Because of this, you have to be sure to include the @type
directory that’s in
your node_modules
as well as any additional locations:
{
// everything before this line
"typeRoots" : ["./node_modules/@types", "./types"],
// everything after this line
}
Once typeRoots
was updated, ts-node
stopped barking at me with Could not
.
find a declaration file for module
As I did try a bunch of things prior, including defining the typeRoots
to a
directory with index.d.ts
and package.d.ts
, I can tell you, the trick here
really is the directory structure of the declaration files.
At this point, everything was good to go. The project / boilerplate is coming
together nicely and I’m excited to launch a new project here in the very near
future.
If you feel like calling me out for being a total noob and/or want to take time
out of your day to *splain me on a better way to go about this, comment below!