Skip to content

Commit 9db3b4c

Browse files
committed
Twoslashed 13
1 parent f557a04 commit 9db3b4c

File tree

3 files changed

+2293
-3147
lines changed

3 files changed

+2293
-3147
lines changed

book-content/chapters/13-modules-scripts-declaration-files.md

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,11 @@ export const playTrack = (track) => {
145145

146146
If we try to import this file into a TypeScript file, we'll get an error:
147147

148-
```typescript
148+
```ts twoslash
149+
// @errors: 2307
149150
// inside of app.ts
150151

151-
import { playTrack } from "./musicPlayer"; // red squiggly line under ./musicPlayer
152-
// Hovering over the error shows:
153-
// Could not find a declaration file for module './musicPlayer'.
152+
import { playTrack } from "./musicPlayer";
154153
```
155154

156155
This error occurs because TypeScript doesn't have any type information for the `musicPlayer.js` file. To fix this, we can create a declaration file with the same name as the JavaScript file, but with a `.d.ts` extension:
@@ -334,18 +333,22 @@ declare function myFunction(): void;
334333

335334
To do this, we can wrap our `declare const` statement in a `declare global` block:
336335

337-
```typescript
336+
```ts twoslash
337+
// @errors: 1038
338+
type Album = {
339+
title: string;
340+
artist: string;
341+
releaseDate: string;
342+
};
343+
344+
// ---cut---
338345
// inside musicUtils.ts
339346
declare global {
340347
declare const ALBUM_API: {
341-
// red squiggly line under declare
342348
getAlbumInfo(upc: string): Promise<Album>;
343349
searchAlbums(query: string): Promise<Album[]>;
344350
};
345351
}
346-
347-
// Hovering over the error shows:
348-
// A 'declare' modifier cannot be used in an already ambient context.
349352
```
350353

351354
This almost works, except for the error. We can't use `declare` inside an ambient context: the `declare global` block is already ambient. So, we can remove the `declare` keyword:
@@ -704,14 +707,10 @@ In some environments like Webpack, it's possible to import files like images tha
704707

705708
Consider this example where several `.png` images are imported. TypeScript doesn't typically recognize PNG files as modules, so it reports an error underneath each import statement:
706709

707-
```tsx
708-
import pngUrl1 from "./example1.png"; // red squiggly line under "./example1.png"
709-
import pngUrl2 from "./example2.png"; // red squiggly line under "./example2.png"
710-
import pngUrl3 from "./example3.png"; // red squiggly line under "./example3.png"
711-
import pngUrl4 from "./example4.png"; // red squiggly line under "./example4.png"
712-
713-
// hovering over "./example1.png" shows:
714-
Cannot find module './example1.png' or its corresponding type declarations.
710+
```ts twoslash
711+
// @errors: 2307
712+
import pngUrl1 from "./example1.png";
713+
import pngUrl2 from "./example2.png";
715714
```
716715

717716
The `declare module` syntax can help. We can use it to declare types for non-JavaScript files.
@@ -825,7 +824,10 @@ Your task is to specify that `DEBUG` is available in this module (and this modul
825824

826825
Let's imagine now that we want our `DEBUG` object to only be accessible through the `window` object:
827826

828-
```tsx
827+
```ts twoslash
828+
// @errors: 2339
829+
import { Equal, Expect } from "@total-typescript/helpers";
830+
// ---cut---
829831
// inside index.ts
830832

831833
const state = window.DEBUG.getState(); // red squiggly line under DEBUG
@@ -835,12 +837,7 @@ type test = Expect<Equal<typeof state, { id: string }>>;
835837

836838
We expect `state` to be an object with an `id` string property, but it is currently typed as `any`.
837839

838-
There's also an error on `DEBUG` that tells us TypeScript doesn't see the `DEBUG` type:
839-
840-
```tsx
841-
// hovering over DEBUG shows:
842-
// Property 'DEBUG' does not exist on type 'Window & typeof globalThis'.
843-
```
840+
There's also an error on `DEBUG` that tells us TypeScript doesn't see the `DEBUG` type.
844841

845842
Your task is to specify that `DEBUG` is available on the `window` object. This will help TypeScript understand the type of `state` and provide the expected type checking.
846843

@@ -852,10 +849,18 @@ The `env` property is an object encapsulating all the environment variables that
852849

853850
Here's an example of using an `envVariable`, along with a test that checks to see if it is a string:
854851

855-
```tsx
852+
```ts twoslash
853+
// @errors: 2344
854+
import { Equal, Expect } from "@total-typescript/helpers";
855+
856+
declare const process: {
857+
env: Record<string, string | undefined>;
858+
};
859+
860+
// ---cut---
856861
const envVariable = process.env.MY_ENV_VAR;
857862

858-
type test = Expect<Equal<typeof envVariable, string>>; // red squiggly line under Equal
863+
type test = Expect<Equal<typeof envVariable, string>>;
859864
```
860865

861866
TypeScript isn't aware of the `MY_ENV_VAR` environment variable, so it can't be certain that it will be a string. Thus, the `Equal` test fails because `envVariable` is typed as `string | undefined` instead of just `string`.
@@ -889,8 +894,13 @@ declare const DEBUG: {};
889894

890895
Now that we've typed `DEBUG`, the error message has moved to be under `getState()`:
891896

892-
```tsx
893-
const state = DEBUG.getState(); // red squiggly line under getState
897+
```ts twoslash
898+
// @errors: 2339
899+
import { Equal, Expect } from "@total-typescript/helpers";
900+
declare const DEBUG: {};
901+
// ---cut---
902+
903+
const state = DEBUG.getState();
894904

895905
type test = Expect<Equal<typeof state, { id: string }>>;
896906
```

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@
598598
"@types/express": "^4.17.13",
599599
"@types/react": "^18.2.8",
600600
"@types/react-dom": "^18.2.4",
601+
"@types/node": "^20.14.2",
601602
"express": "^4.18.1",
602603
"react": "^18.2.0",
603604
"react-dom": "^18.2.0",

0 commit comments

Comments
 (0)