Intermediate TypeScript, v2

Intermediate TypeScript, v2 Importing Non-TypeScript Files

Learning Paths:
Topics:
Check out a free preview of the full Intermediate TypeScript, v2 course:
The "Importing Non-TypeScript Files" Lesson is part of the full, Intermediate TypeScript, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Mike discusses how to import non-TypeScript files, such as images or JSON, in TypeScript when using a bundler like Webpack or Parcel. How to create a global declaration file to resolve import errors for non-TypeScript files and examples of importing image files and URL modules are also covered in this segment.

Get Unlimited Access Now

Transcript from the "Importing Non-TypeScript Files" Lesson

[00:00:00]
>> All right, we talked about TypeScript ES modules, importing non-TypeScript things. So if you're using a bundler like webpack, or parcel, or snowpack, or even Babel, which is not a bundler, but it's a transpiler. Depending on your Babel plugins or your webpack loaders, you may import things like file.png.

[00:00:22] And if you don't do anything to support this, you'll get errors like this. It's saying, what is file.png? I can't find a file.png.ts file for you to import, what's going on here? So what we can do to address this, so here's our scenario. You can have what's called a global declaration file.

[00:00:49] Let's see, you can have a file called global.d.ts. This is where you would put type information, ambient type information. We'll talk more about what this is later, but this is equivalent to the d.ts files that are part of your compiled output. global.d.ts is sort of a place where you can do the highest level adjustments to the way TypeScript understands.

[00:01:19] The types that ship with TypeScript, so the way it treats certain things. So I'm gonna grab this piece of code, I'm gonna paste it in here, we're gonna witness that it actually solved the problem, and then we'll look back and we'll try to understand what it means. Problem goes away.

[00:01:36] In fact, if I click this, I thought VS Code might load the image. It's gonna take me to the module declaration here. And so what are we saying here? Well, we're saying, I have a certain type of module and it's anything that ends with the extension png. And what I want you to regard that module as containing is it should have a string.

[00:02:10] And you won't see this, cuz in a module declaration like this, we'll talk more about this, but we're not exporting this, right? You have to explicitly export things from module declarations just like you have to explicitly export things from modules. So we're saying, okay, I'm gonna create a comp thing, we're not initializing it or anything, and we could not in this context, but then I want you to treat it as a default export.

[00:02:38] Maybe we could even do this just to abbreviate it. Nope, I knew there was a reason because it has to be kind of value-ish for us to export it, which is a little bit of a screwy thing because you're not allowed to have values in this file. You can have declarations that sort of represent values, but I absolutely cannot do this, not allowed.

[00:03:07] This file can only contain types, it's just types. But in essence, what that lets us do here is, if I hover over image, look at that, it's a string, it's a const declaration of a string. And this is kind of how you might see webpack using this, right?

[00:03:27] I mean, maybe I haven't done this in a while, but probably gives you some way to get the URL of this image, which includes the hash in the bundle name. Or where it does cache busting and adds little fingerprints like MT5 checksums to images so that when they change, you request them when appropriate.

[00:03:48] So it creates the right URL for you, and you'll obtain it here. It might even, if it were really fancy, give you dimensions of this image. So I don't know maybe you could use that information as you build your layout out, right? All of that is knowable at build time, and so it can assemble that information together and feed it to you.

[00:04:09] But this is just a little hack, it's not really a hack, but it's the adjustment that you have to tell TypeScript about so that it can understand when you're importing things that are not code. I mean, it could also be a JSON file. There are other ways to handle JSON, but it would be perfectly fine to do it this way.

[00:04:26] Anything that's in the webpack world like a loader, where it has the opportunity to transform things for you, this would be super, super useful. Why is it that whenever I create a module declaration for png, for example, and I try to jump to that file in my IDE, it navigates to the module declaration and not the actual file?

[00:04:45] Because that's the way TypeScript thinks about these things. It treats this as a module, it doesn't know it's an image. It has no idea that it's an image. It doesn't even know that it's a file. What if you did this? We're gonna do something really weird. Well, that's odd.

[00:05:15] What if we did this? Just make it not png, you can make it HTML. And then up here, we can say, okay. Possible illegal module characters. We'll see if the escapes actually work here. Or we do this, Something like that. All right, so we're saying if a module begins with http://, our default export treat default export as if it's the return type of the fetch function.

[00:06:23] And look, we go back here, and look at that, it's a promise that resolves to a response. So this clearly is not a file in my project, right, I'm giving it a URL. This is super, super unusual, but I make this point. I'm showing you this example because the name of the module here could be anything, it doesn't necessarily have to be a local file.

[00:06:47] And so all that's safe for TypeScript to do is to say, all right, see, there it did try to jump to the URL. It just took me here, and it's saying, you want the type, the declaration, where this module exists? This is the best I've got for you, this is my source of truth for understanding the types of this module.