Table of Contents
Introduction
Introduction
Mike North introduces TypeScript as a programming language, compiler, and a langage server.TypeScript is a syntactic superset of JavaScript, built upon the existing JavaScript language. It allows for more robust linting, better IDE tooling, and compile-time error checking.Course Project Setup
Mike walks through the project setup guide which is located in the README.md file in the GitHub repository. The project requires Yarn for dependency management. The notes folder contains a Markdown file with code snippets and other information for each topic.
Features
Volta
Mike explains the difference between Volta and the Node Version Manager (NVM). Volta seamlessly switches between command-line tool versions depending on a project's requirements. This segment also addresses why Yarn is recommended with TypeScript and Volta's compatibility between Yarn and NPM.Optional Chaining & Nullish Coalescing
Mike demonstrates TypeScript language features added in versions 3.7 and 3.8. This segment covers optional chaining, nullish coalescing, ECMAScript private fields, and namespace exports.Tuple Types & Recursive Type Aliases
Mike demonstrates TypeScript language features added in versions 4.0 and 4.1. This segment covers tuple types, recursive type aliases, and template type literals.ts-ignore
Mike introduces the @ts-expect-error assertion added to TypeScript 3.9. This assertion is more descriptive than @ts-ignore because, rather than just ignoring the next line, it is explicitly ignoring a compiler error.Error Handling with Unknown
Mike uses the "unknown" type on an error property in a catch() clause. If an error is thrown as a String instead of an Error object, the catch() class can still handle the error and determine its type.Declaration Files & Type-only Imports
Mike explains how declaration files can be generated from JavaScript files so projects containing JavaScript code can still offer first-class TypeScript support. Modules also support type-only imports so compilers can skip importing entire codebases when the type information is the only requirement.TypeScript in Apps vs Libraries
Mike describes the benefits TypeScript brings to both library and application development. Any codebase benefits from TypeScript's in-editor documentation and the formalized contracts it creates between components. Applications benefit from better encapsulation and the descriptive changes between major version upgrades. Libraries benefit from a more descriptive public API and tighter semantic versioning.
Project Implementation
Creating a Project from Scratch
Mike creates an empty TypeScript project to demonstrate best practices around dependency management, and configuration. The project uses Volta to ensure the correct version of Node and Yarn will be installed. The "dev" NPM script uses the "--watch" flag to rebuild the project when a file is changed and the "--preserveWatchOutput" flag to keep console information from the last rebuild.tsconfig
Mike walks through common settings used in the tsconfig.json file. Setting the rootDir property omits the source directory from being included in the output directory. Using properties like noUnusedLocals and noUnusedParameters adheres to coding standards and can be more consistent than linting rules.Configuring ESLint
Mike configures ESLint for the TypeScript project. ESLint has a series of questions that help determine what plugins are required and how to configure the linting rules. Additional customization can be added in the .eslintrc.json configuration file.Testing
Mike installs Jest and the type definitions for Jest to enable testing in the TypeScript Project. The preset-env and preset-typescript Babel plugins allow the test code to be written in TypeScript and the source code can be tested without first being transpiled to JavaScript.
API Extraction
API Extractor Setup
Mike adds the API Extractor and API Documentor modules to the project to generate surface reports and documentation. The API Extractor is configured to include methods based on build version, and exports the surface reports to an "/etc" directory.Running API Extractor
Mike runs API Extractor after building the project. The TypeScript declaration files are analyzed, and API Extractor exports the surface reports.API Documenter
Mike generates the documentation files using the API Documenter module. The GitHub repository is configured to use the docs folder as the source for the Github Pages site. This segment also discusses alternative documentation libraries and the compatibility between TypeScript and JavaScript.strict In-Depth
Mike explains the different strict type-checking options that can be configured in the tsconfig.json configuration file. This segment covers noImplicitAny, noImplicitThis, strictBindCallApply, strictNullChecks, strictFunctionTypes, and strictPropertyInitialization.Even More strict
Mike covers additional strict type-checking options which prevent unused variables and implicit returns from being included in the project. The stripInternal property can be used to remove exported private functions from the project's type information.Viral Options
Mike explains why the allowSyntheticDefaultImports, esModuleInterop, and skipLibCheck cause type information to be leaked out of a library and should be avoided. This segment demonstrates alternative methods for importing code from modules without enabling these properties.
Converting a Project to TypeScript
Converting a Project to TypeScript
Mike discusses the steps for converting a JavaScript project to a TypeScript project. Files should be renamed with a .ts extension and only have non-type-checking errors fixed. Then files should be only allowed "explicit any" type information. Lastly, enable strict mode and replace the remaining "explicit any" object with a specific type.Typing a Project to strict
Mike begins converting the project to TypeScript by renaming the old files to the appropriate extension. When files are renamed in a repository, the code should be committed before additional changes are made so the history is preserved. Disable strict mode and allow "implicit any" types to be used before debugging errors.Typing React Components
Mike adds the React.FunctionComponent type to most of the untyped React components. A React component's props can use the <any> type parameter.Typing 3rd Party Libraries
Mike updates the compiler settings to not allow implicit any types. Parameter types are copied from JS Doc comments or explicitly typed as an "any". This segment also explains using the hard-privacy syntax to prevent a property from being accessible outside of the class.Enabling Stricter Settings
Mike enables the noUnusedLocals and noImplicitReturns rules in the tsconfig.json file, and recompiles the project.Using ESLint
Mike install @typescript-eslint/eslint-parser so ESLint can interpret the TypeScript code and @typescript-eslint/eslint-plugin so ESLint can provide feedback about the TypeScript code.Using Interfaces
Mike uses an interface to import type information for API calls in the application's data layer. Interfaces do not contain any implementation code so the impact on the application's codebase size is minimal.Local Type Overrides
Mike demonstrates how type definitions in third-party libraries can be overridden locally in a project. The TypeScript compiler can be configured to check a local folder for type definitions before locating the original definition files in the node_modules folder.Types at Runtime
Mike creates a type guard which will add type-checking logic to asynchronous runtime data. The type guard uses assertions to throw runtime errors when the asynchronous data does not meet the validation rules.Converting to TypeScript Q&A
Mike answers questions about handling large type definition files, moving configuration files into subdirectories, maintaining type guard files, and how to handle publishing new versions of a library when there are still local type overrides.
Tests & Linting
Tests for Types
Mike emphasises the importance of writing tests in a TypeScript project. A test suite can be configured to run against nightly TypeScript builds to ensure compatibility with the project.dtslint Setup
Mike configures dtslint to test the TypeScript declaration files for style and correctness. This helps guard against compatibility regressions.Writing dtslint Assertions
Mike uses dtslint to test the project code against nightly TypeScript builds. Comments specific to dslint are added in the code specifying the minimum TypeScript version and annotating test assertions. Using the tsd library instead of dtslint eliminates the need to use special comments but can only test against a single TypeScript version.