Table of Contents
Course Project SetupMike 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.
VoltaMike 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 CoalescingMike 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 AliasesMike 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-ignoreMike 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 UnknownMike 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.
TypeScript in Apps vs LibrariesMike 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.
Creating a Project from ScratchMike 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.
tsconfigMike 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 ESLintMike 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.
API Extractor SetupMike 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 ExtractorMike runs API Extractor after building the project. The TypeScript declaration files are analyzed, and API Extractor exports the surface reports.
strict In-DepthMike 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 strictMike 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 OptionsMike 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
Typing a Project to strictMike 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 ComponentsMike 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 LibrariesMike 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 SettingsMike enables the noUnusedLocals and noImplicitReturns rules in the tsconfig.json file, and recompiles the project.
Using ESLintMike 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 InterfacesMike 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 OverridesMike 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 RuntimeMike 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&AMike 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 TypesMike 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 SetupMike configures dtslint to test the TypeScript declaration files for style and correctness. This helps guard against compatibility regressions.
Writing dtslint AssertionsMike 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.