External Libraries 9 exercises

Create a Declarations File to Override Types

Trying the declare module Syntax

Let's do an experiment with the declare module syntax inside of the solution file.

This will put a module into global scope.

Loading solution


[0:01] I've set up this slightly differently. I've given it a different global name fake-animation-lib-solution. What we're going to do is we're going to need to create a declaration file for this. The reason is you would think you would be able to do something like this, declare module, let's say, fake-animation-lib-solution.

[0:22] Now what this syntax does is it basically says, we have this module in scope called fake-animation-lib-solution. I'm going to declare what that thing returns, and declare in general puts things into a global scope. What I can do is I can say...I'm pretty sure I might be able to say export type Wow for instance and say Wow is a string for instance.

[0:46] Now, I think I might be able to import...yeah, I can import Wow from this. This is weird. You can actually make modules return different types and different things, based on what you pass in here. That's pretty useful. What you'll notice is you can't, if you do export function getAnimatingState and then you get it to return a number, for instance.

[1:11] This actually isn't going to work because it's already like declared within this block. We can't overwrite stuff from in here. Weirdly we can add stuff using this syntax, but we can't overwrite it. How do we overwrite it? We can actually move this, and I'm actually going to create a file here. Let's say 26.5-declaration.solution.d.ts.

[1:39] What we're going to do inside here is if I open up the other file just beside it, then we're going to see things slightly change. I'm going to move this declare module from inside here into there. I'll just move this over so you can see it properly. Now we've got declare module fake-animation-lib-solution, and now getAnimatingState has no exported member getAnimatingState.

[2:04] This thing now is now not available whereas Wow is still available. If I remove Wow now it's available there. By putting it inside here what we're doing is we're saying this is now the only source of truth for this module. That's fairly useful. Now what we can do is we can export function getAnimatingState, and this is going to return the thing that we want it to return.

[2:31] Now before-animation, animating, and after-animation is now the return type of getAnimatingState. We've overridden the actual module that we care about. This is of course wildly unsafe, extremely unsafe because we can do anything here. We can do a typo, and now we're changing the actual types of the library that we're exporting.

[2:56] Sometimes you just don't have a choice, and you want to be able to override the module to be able to give the types that you want. We can even extract this into its own type if we want to. Type AnimatingState. If we put it here, then it's going to be AnimatingState and we can actually extract that so we get, where is it, AnimatingState there.

[3:18] This is really useful when you want to just blast out the types that were there before and put your own types in their place. I'm intrigued too. If I say type AnimatingState here, does it still export it? Yes, it does still export it. That's interesting. There are things I don't know about this solution.

[3:37] I haven't really used this in production, but it's a really valuable tool in your toolbox. The TypeScript docs are pretty good on it, in terms of giving you the understanding you need to be able to process it and use it.