## Compiling TypeScript
-- ### Goals - Understand how TS compiles to JS - Take advantage of the compiler's type inference - Compose types with interfaces & generics - Specify compiler settings with `tsconfig.json` -- ### Ready? # Let's go!
## TS & JS: BFFs
--
-- ### Compiling TS to JS
`file.ts`
`tsc`
`file.js`
-- Earlier, we ran this command: ```zsh tsc --checkJs --noEmit --strict checkMe.js ``` What do those all those flags do exactly?? -- flag | tells compiler to --- | --- `--checkJs` | look at `.js` files (default: `.ts` only) `--strict` | be more nitpicky `--noEmit`| ??? -- ### Emitted files In the last exercise, we ran: `tsc typeMe.ts` This compiled our TS to JS and _emitted_ a new file `typeMe.js` -- ### Inputs & outputs option | Inputs | Outputs --- | --- | --- (default) | `.ts` | `.js` `--checkJs` | `.ts` & `.js` | `.js` `--noEmit` | `.ts` | nothing! -- ### Into the JS multiverse  -- What do you notice about the emitted `typeMe.js`? Try rerunning the command with this flag: ```zsh tsc --target es2020 typeMe.ts ``` What do you notice now? -- ### Compiler Targets `tsc` _targets_ a particular version of JS for its output target | compiled code runs in --- | --- `es5` (default) | older browsers `es6`/`es2015` | most browsers `esnext` | newest hottest browsers -- ### Fine-tuning emitted JS Other options give us even more control what ends up in the emitted JS, for example: ```zsh tsc --removeComments typeMe.ts ``` -- ### Compiler Options Our collection of `tsc` flags is growing! `--strict` `--checkJs` `--noEmit` `--target
` `--removeComments` -- 
## `tsconfig.json` -- ### Exercise time! [`3-compiler/exercise/README.md`](https://github.com/vakila/typescript-first-steps/tree/main/3-compiler/exercise) ```zsh cd 3-compiler/exercise/ ``` -- ### Step 1: Install deps & run tests ```zsh npm i ``` ```zsh npm run test ``` We have some work to do to get these tests passing! -- ### Step 2: Setup TypeScript Install TS as a dev dependency: ```zsh npm i -D typescript ``` -- Add a `compile` script in `package.json`: ```json "scripts": { "test": "vitest", "compile": "tsc" }, ``` -- What happens when you run `npm run compile`? -- ### Step 3: Create `tsconfig.json` ```zsh tsc --init ``` Read through the config file. What do you notice? -- Now try compiling again: ```zsh npm run compile ``` --  -- option | emits | used for e.g. --- | --- | --- `declaration` | `.d.ts` | intellisense `declarationMap` | `.d.ts.map` | 'Go to definition' `sourceMap` | `.js.map` | debugging _disable these options if you want!_
## Fancy types  -- ### Interfaces ```ts interface User { username: string; id: number; } const u: User = { username: 'anjana', id: 1} ``` -- ### Extending interfaces ```ts interface Human extends User { fullname: string; } interface AiAgent extends User { modelName: string; } ``` -- ```ts const batman: Human = { username: 'batman', id: 2, fullname: 'Bruce Wayne' }; const notman: Human = { username: 'catwoman', id: 1 }; // Error! const notbot: AiAgent = { modelName: 'sonnet'}; // Error! const yesbot: AiAgent = { username: 'claude', id: 3, modelName: 'haiku' }; // OK ``` -- ### Async code ```ts function wave(): string { return ":wave:"; } async function asyncWave(): Promise
{ return ":wave:"; } const waveString = wave(); const wavePromise = asyncWave(); waveString.length; // 6 wavePromise.length; // Error! ``` -- ### Type parameters ```ts const promisedNum: Promise
= Promise.resolve(5); const promisedStr: Promise
= Promise.resolve('5'); const brokenPromise: Promise
= Promise.resolve(null); // Error! ``` -- ### Generics ```ts type Nullable
= T | null; let nullishNum: Nullable
= 4; nullishNum = 5; // OK nullishNum = null; // OK nullishNum = 'oh no'; // Error! let stringishNull: Nullable
= null; stringishNull = 'I exist!'; // Ok stringishNull = 5; // Error! stringishNull = undefined; // Error! ``` -- ### Builtin utility types `Readonly
` `Partial
` `Pick
` `Omit
` ...and [many more!](https://www.typescriptlang.org/docs/handbook/utility-types.html) -- ```ts const editable: User = { username: 'fornow', id: 1 }; editable.username; // 'fornow' editable.username = 'nomore' // OK const fixed: Readonly
= { username: 'forever', id: 2 } fixed.username; // 'forever'; fixed.username = 'wontwork'; // Error! ``` -- ```ts const noId: Partial
= { username: 'noid' }; const noUsername: Partial
= { id: 1 }; const allOk: Partial
= { username: 'ok', id: 2}; const noneOk: Partial
= {}; const notOk: Partial
= {invalid: 'property'}; // Error! ``` -- ```ts const batman: Human = {username: 'batman', id: 2, fullname: 'Bruce Wayne' }; const justId: Pick
= { id: 3 }; const justNames: Pick
= {username: 'catwoman', fullname: 'Selina Kyle' }; const wontWork: Pick
= {fullname: 'Alfred Pennyworth', id: 4}; ``` -- ```ts const noUname: Omit
= { fullname: 'Alfred Pennyworth', id: 4 }; const onlyUname: Omit
= { username: 'butler', }; const equivalent: Pick
= onlyUname; ```
### Typechecking in the dev workflow -- ``` tsc --watch ``` Re-runs compiler when you save edits (but can get real slow!) -- ```json "scripts" : { "test": "tsc --noEmit && vitest", } ``` If `tsc` fails, `vite build` won't run!
### Back to our exercise! -- ## Update `test` script to check types first ```json "scripts": { "test": "tsc --noEmit && vitest", "compile": "tsc" }, ``` -- ## Step 4: Fix the code! Declare the missing types in `compileMe.ts` so that: - TS compiles without errors - all tests pass
### Telling the compiler to hush (when you know better)  -- ### `any` ```ts let notHelpful: any = 'whatever'; notHelpful = 'hello'; notHelpful = 5; notHelpful.toUpperCase(); ``` --  -- ### `@ts-ignore` ```js // @ts-ignore function (anything) { //... } ``` --  -- 
## We're off and typing!  -- We've covered a lot so far: - TS vs JS - Installing & using `tsc` and `tsx` - Type annotations & aliases - Composing types with Unions, Interfaces, & Generics - Compiling TS to JS with different options --  -- ### Coming up: - Configuring TS for various use cases - Refining your dev workflow - Exploring the TS ecosystem - Ensuring end-to-end type safety