Table of Contents
Setup & Course ProjectMike explains the process of installing Volta and provides instructions on cloning the workshop repository and installing the necessary dependencies using Yarn. The Slack-style project application is introduced, and the project's file structure is explained.
Building a TypeScript Library
.gitignore & package.jsonMike walks through setting up a TypeScript library within a project. Volta is installed, a package.json file is created, and versions for node and yarn are pinned. Mike emphasizes the importance of using the latest LTS node version and avoiding big changes that can disrupt the project.
Install TypeScript & Configure tsconfig.jsonMike installs the TypeScript compiler and creates a tsconfig.json file. The available configuration options are examined and TypeScript is configured for all files in the src directory and the .eslintrc.js file.
Install ESLintMike installs ESLint in the project. An index.ts file is added with some default code and build command is created to generate the dist folder. ESLint is initialized in the project using the CLI.
Configure ESLintMike adjusts the ESLint config file, adding TypeScript-specific rules and specifying the TS config file location. The lint command is run, and initial linting errors are fixed in the index.ts file.
Setup Jest TestingMike installs and configures both Jest and Babel to work together for running TypeScript test files without an explicit build step. The tests are run, and any errors are fixed.
Setup Test & Watch ScriptMike explains how to improve the development workflow by setting up a watch mode for both the build and test scripts. The concurrently package is installed and used to run both scripts in parallel.
API ReportingMike adds an API surface report and documentation to the project by installing the api-extractor and api-documenter packages. The API Extractor package generates API report in a markdown file and can adapt the report based on alpha, beta, and public release statuses.
API DocumentationMike uses the api-documenter package to generate documentation for the library's APIs. JSDoc comments are used to flag methods based on their version availability, like alpha and beta. A code change is made to the API, and the API Extractor warning about the change is explained.
tsconfig StrictnessMike discusses various TypeScript compiler options and their implications, such as noImplicitAny, noImplicitThis, strictNullChecks, strictFunctionTypes, and more. Fixing TypeScript/ESLint errors in a test file by specifying the correct path for the declaration file is also demonstrated.
Converting an Application to TypeScript
TypeScript Migration OverviewMike discusses converting a project to TypeScript and gradually improving the typing and linting. Making incremental passes and staying focused on specific tasks to avoid introducing bugs is encouraged. The steps include getting TypeScript into the build toolchain, renaming files to TS, getting rid of implicit any's, bringing in definitely-typed packages, creating interfaces for domain modeling, and working on Boolean expressions.
Forbidding Implicit anyMike demonstrates the next step in the TypeScript conversion, which is disallowing implicit any types. Setting the noImplicitAny flag to true for an entire project can be problematic since there's a wide surface area for changes. Instead, creating a new tsconfig file in an individual subfolder and starting there can make the process more incremental.
DefinitelyTyped & VersioningMike explains that declaration files, denoted by the .d.ts extension, contain type information but no runnable code. The community-run DefinitelyTyped repository is toured, and students are encouraged to contribute to projects that need type information or bug fixes. Challenges with versioning are also discussed.
Type AcquisitionsMike explains where TypeScript looks for type declarations, such as the top level, type roots, explicit module declarations, and custom type roots. Prioritization of file types is discussed, and the importance of publishing accurate declaration files for libraries is emphasised.
Pure Type InformationMike defines interfaces for important components of the Slack app, such as messages, channels, teams, and users. These interfaces are applied in various parts of the codebase, including React components and data functions.
Typing React PropsMike demonstrates two different methods for adding types to React component props. The React.FC type is favored over using a custom interface because it would require less refactoring if any core React functionality changed in a future version.
Local Type OverridesMike demonstrates how to patch imported types locally in the project. Type declaration files can be created to override the types of imported modules, which removes blocks and allows a team to continue to develop while the imported library is fixed.
null, undefined & boolean OperatorsMike applies ESLint rules and increases the strictness of the files in the utils folder. Similar to defining an additional tsconfig file, the new ESLint rules can be defined in the overrides object and the rules can be scoped to a specific directory.
Runtime, Package, & Test Type Guards
Types at RuntimeMike discusses type checking at runtime and introduces the concept of type guards. Performing full type checking at runtime can be expensive and slow down an application. Instead, using type guards to perform type checking at runtime can add type safety to API responses or other places in the application like a data layer.
Local PackagesMike imports the chat-stdlib library project into the chat project using yarn workspaces. This simulates how a monorepo would be architected because it helps enable encapsulation and manage complexity. The library is added as a dependency in the project's package.json file and imports are refactored.
Yarn FocusMike demonstrates the focus feature of Yarn workspaces, which removes unnecessary dependencies from the node modules folder, leaving only the dependencies needed for a specific part of the project. This allows for a more focused and efficient development process when working on different modules or components of a large-scale project.
Tests for TypesMike compares positive and negative test cases for types in TypeScript. While positive test cases are easy to write, negative test cases are important to catch mistakes that should not be compilable. Two tools for writing negative test cases are introduced: DTS Lint and TSD.