[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-71200":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":25,"hasPages":25,"topics":26,"createdAt":10,"pushedAt":10,"updatedAt":38,"readmeContent":39,"aiSummary":40,"trendingCount":16,"starSnapshotCount":16,"syncStatus":17,"lastSyncTime":41,"discoverSource":42},71200,"typescript-book","gibbok\u002Ftypescript-book","gibbok","The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.","https:\u002F\u002Fgibbok.github.io\u002Ftypescript-book\u002F",null,"JavaScript",10316,608,53,1,0,2,11,22,6,43.35,"Other",false,"main",true,[27,28,29,30,31,32,5,33,34,35,36,37],"book","free","javascript","javascript-book","learn-typescript","typescript","typescript-guide","typescript-guidebook","typescript-language","typescript-learning","typescript-tutorials","2026-06-12 02:02:49","# The Concise TypeScript Book\n\nThe Concise TypeScript Book provides a comprehensive and succinct overview of TypeScript's capabilities. It offers clear explanations covering all aspects found in the latest version of the language, from its powerful type system to advanced features. Whether you're a beginner or an experienced developer, this book is an invaluable resource to enhance your understanding and proficiency in TypeScript.\n\nThis book is completely Free and Open Source.\n\nI believe that high-quality technical education should be accessible to everyone, which is why I keep this book free and open.\n\nIf the book helped you squash a bug, understand a tricky concept, or advance in your career, please consider supporting my work by paying what you want (suggested price: 15 USD) or sponsoring a coffee. Your support helps me keep the content up to date and expand it with new examples and deeper explanations.\n\n[![Buy Me a Coffee](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fbuy_me_a_coffee-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https:\u002F\u002Fwww.buymeacoffee.com\u002Fsimonepoggiali)\n\n[![Donate](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDonate-PayPal-green.svg)](https:\u002F\u002Fwww.paypal.com\u002Fdonate\u002F?business=QW82ZS956XLFY&no_recurring=0&currency_code=EUR)\n\n## Translations\n\nThis book has been translated into several language versions, including:\n\n[Chinese](https:\u002F\u002Fgithub.com\u002Fgibbok\u002Ftypescript-book\u002Fblob\u002Fmain\u002FREADME-zh_CN.md)\n\n[Italian](https:\u002F\u002Fgithub.com\u002Fgibbok\u002Ftypescript-book\u002Fblob\u002Fmain\u002FREADME-it_IT.md)\n\n[Portuguese (Brazil)](https:\u002F\u002Fgithub.com\u002Fgibbok\u002Ftypescript-book\u002Fblob\u002Fmain\u002FREADME-pt_BR.md)\n\n[Swedish](https:\u002F\u002Fgithub.com\u002Fgibbok\u002Ftypescript-book\u002Fblob\u002Fmain\u002FREADME-sv_SE.md)\n\n[Bulgarian](https:\u002F\u002Fgithub.com\u002Fgibbok\u002Ftypescript-book\u002Fblob\u002Fmain\u002FREADME-bg_BG.md)\n\n## Downloads and website\n\nYou can also download the Epub version:\n\n[https:\u002F\u002Fgithub.com\u002Fgibbok\u002Ftypescript-book\u002Ftree\u002Fmain\u002Fdownloads](https:\u002F\u002Fgithub.com\u002Fgibbok\u002Ftypescript-book\u002Ftree\u002Fmain\u002Fdownloads)\n\nAn online version is available at:\n\n[https:\u002F\u002Fgibbok.github.io\u002Ftypescript-book](https:\u002F\u002Fgibbok.github.io\u002Ftypescript-book)\n\n## Table of Contents\n\n\u003C!-- markdownlint-disable MD004 -->\n- [The Concise TypeScript Book](#the-concise-typescript-book)\n  - [Translations](#translations)\n  - [Downloads and website](#downloads-and-website)\n  - [Table of Contents](#table-of-contents)\n  - [Introduction](#introduction)\n  - [About the Author](#about-the-author)\n  - [TypeScript Introduction](#typescript-introduction)\n    - [What is TypeScript?](#what-is-typescript)\n    - [Why TypeScript?](#why-typescript)\n    - [TypeScript and JavaScript](#typescript-and-javascript)\n    - [TypeScript Code Generation](#typescript-code-generation)\n    - [Modern JavaScript Now (Downleveling)](#modern-javascript-now-downleveling)\n  - [Getting Started With TypeScript](#getting-started-with-typescript)\n    - [Installation](#installation)\n    - [Configuration](#configuration)\n    - [TypeScript Configuration File](#typescript-configuration-file)\n      - [target](#target)\n      - [lib](#lib)\n      - [strict](#strict)\n      - [module](#module)\n      - [moduleResolution](#moduleresolution)\n      - [esModuleInterop](#esmoduleinterop)\n      - [jsx](#jsx)\n      - [skipLibCheck](#skiplibcheck)\n      - [files](#files)\n      - [include](#include)\n      - [exclude](#exclude)\n    - [importHelpers](#importhelpers)\n    - [Migration to TypeScript Advice](#migration-to-typescript-advice)\n  - [Exploring the Type System](#exploring-the-type-system)\n    - [The TypeScript Language Service](#the-typescript-language-service)\n    - [Structural Typing](#structural-typing)\n    - [TypeScript Fundamental Comparison Rules](#typescript-fundamental-comparison-rules)\n    - [Types as Sets](#types-as-sets)\n    - [Assign a type: Type Declarations and Type Assertions](#assign-a-type-type-declarations-and-type-assertions)\n      - [Type Declaration](#type-declaration)\n      - [Type Assertion](#type-assertion)\n      - [Ambient Declarations](#ambient-declarations)\n    - [Property Checking and Excess Property Checking](#property-checking-and-excess-property-checking)\n    - [Weak Types](#weak-types)\n    - [Strict Object Literal Checking (Freshness)](#strict-object-literal-checking-freshness)\n    - [Type Inference](#type-inference)\n    - [More Advanced Inferences](#more-advanced-inferences)\n    - [Type Widening](#type-widening)\n    - [Const](#const)\n      - [Const Modifier on Type Parameters](#const-modifier-on-type-parameters)\n      - [Const assertion](#const-assertion)\n    - [Explicit Type Annotation](#explicit-type-annotation)\n    - [Type Narrowing](#type-narrowing)\n      - [Conditions](#conditions)\n      - [Throwing or returning](#throwing-or-returning)\n      - [Discriminated Union](#discriminated-union)\n      - [User-Defined Type Guards](#user-defined-type-guards)\n      - [Switch-true narrowing](#switch-true-narrowing)\n  - [Primitive Types](#primitive-types)\n    - [string](#string)\n    - [boolean](#boolean)\n    - [number](#number)\n    - [bigInt](#bigint)\n    - [Symbol](#symbol)\n    - [null and undefined](#null-and-undefined)\n    - [Array](#array)\n    - [any](#any)\n  - [Type Annotations](#type-annotations)\n  - [Optional Properties](#optional-properties)\n  - [Readonly Properties](#readonly-properties)\n  - [Index Signatures](#index-signatures)\n  - [Extending Types](#extending-types)\n  - [Literal Types](#literal-types)\n  - [Literal Inference](#literal-inference)\n  - [strictNullChecks](#strictnullchecks)\n  - [Enums](#enums)\n    - [Numeric enums](#numeric-enums)\n    - [String enums](#string-enums)\n    - [Constant enums](#constant-enums)\n    - [Reverse mapping](#reverse-mapping)\n    - [Ambient enums](#ambient-enums)\n    - [Computed and constant members](#computed-and-constant-members)\n  - [Narrowing](#narrowing)\n    - [typeof type guards](#typeof-type-guards)\n    - [Truthiness narrowing](#truthiness-narrowing)\n    - [Equality narrowing](#equality-narrowing)\n    - [In Operator narrowing](#in-operator-narrowing)\n    - [instanceof narrowing](#instanceof-narrowing)\n  - [Assignments](#assignments)\n  - [Control Flow Analysis](#control-flow-analysis)\n  - [Type Predicates](#type-predicates)\n  - [Discriminated Unions](#discriminated-unions)\n  - [The never Type](#the-never-type)\n  - [Exhaustiveness checking](#exhaustiveness-checking)\n  - [Object Types](#object-types)\n  - [Tuple Type (Anonymous)](#tuple-type-anonymous)\n  - [Named Tuple Type (Labeled)](#named-tuple-type-labeled)\n  - [Fixed Length Tuple](#fixed-length-tuple)\n  - [Union Type](#union-type)\n  - [Intersection Types](#intersection-types)\n  - [Type Indexing](#type-indexing)\n  - [Type from Value](#type-from-value)\n  - [Type from Func Return](#type-from-func-return)\n  - [Type from Module](#type-from-module)\n  - [Mapped Types](#mapped-types)\n  - [Mapped Type Modifiers](#mapped-type-modifiers)\n  - [Conditional Types](#conditional-types)\n  - [Distributive Conditional Types](#distributive-conditional-types)\n  - [infer Type Inference in Conditional Types](#infer-type-inference-in-conditional-types)\n  - [Predefined Conditional Types](#predefined-conditional-types)\n  - [Template Union Types](#template-union-types)\n  - [Any type](#any-type)\n  - [Unknown type](#unknown-type)\n  - [Void type](#void-type)\n  - [Never type](#never-type)\n  - [Interface and Type](#interface-and-type)\n    - [Common Syntax](#common-syntax)\n    - [Basic Types](#basic-types)\n    - [Objects and Interfaces](#objects-and-interfaces)\n    - [Union and Intersection Types](#union-and-intersection-types)\n  - [Built-in Type Primitives](#built-in-type-primitives)\n  - [Common Built-in JS Objects](#common-built-in-js-objects)\n  - [Overloads](#overloads)\n  - [Merging and Extension](#merging-and-extension)\n  - [Differences between Type and Interface](#differences-between-type-and-interface)\n  - [Class](#class)\n    - [Class Common Syntax](#class-common-syntax)\n    - [Constructor](#constructor)\n    - [Private and Protected Constructors](#private-and-protected-constructors)\n    - [Access Modifiers](#access-modifiers)\n    - [Get and Set](#get-and-set)\n    - [Auto-Accessors in Classes](#auto-accessors-in-classes)\n    - [this](#this)\n    - [Parameter Properties](#parameter-properties)\n    - [Abstract Classes](#abstract-classes)\n    - [With Generics](#with-generics)\n    - [Decorators](#decorators)\n      - [Class Decorators](#class-decorators)\n      - [Property Decorator](#property-decorator)\n      - [Method Decorator](#method-decorator)\n      - [Getter and Setter Decorators](#getter-and-setter-decorators)\n      - [Decorator Metadata](#decorator-metadata)\n    - [Inheritance](#inheritance)\n    - [Statics](#statics)\n    - [Property initialization](#property-initialization)\n    - [Method overloading](#method-overloading)\n  - [Generics](#generics)\n    - [Generic Type](#generic-type)\n    - [Generic Classes](#generic-classes)\n    - [Generic Constraints](#generic-constraints)\n    - [Generic contextual narrowing](#generic-contextual-narrowing)\n  - [Erased Structural Types](#erased-structural-types)\n  - [Namespacing](#namespacing)\n  - [Symbols](#symbols)\n  - [Triple-Slash Directives](#triple-slash-directives)\n  - [Type Manipulation](#type-manipulation)\n    - [Creating Types from Types](#creating-types-from-types)\n    - [Indexed Access Types](#indexed-access-types)\n    - [Utility Types](#utility-types)\n      - [Awaited\\\u003CT\\>](#awaitedt)\n      - [Partial\\\u003CT\\>](#partialt)\n      - [Required\\\u003CT\\>](#requiredt)\n      - [Readonly\\\u003CT\\>](#readonlyt)\n      - [Record\\\u003CK, T\\>](#recordk-t)\n      - [Pick\\\u003CT, K\\>](#pickt-k)\n      - [Omit\\\u003CT, K\\>](#omitt-k)\n      - [Exclude\\\u003CT, U\\>](#excludet-u)\n      - [Extract\\\u003CT, U\\>](#extractt-u)\n      - [NonNullable\\\u003CT\\>](#nonnullablet)\n      - [Parameters\\\u003CT\\>](#parameterst)\n      - [ConstructorParameters\\\u003CT\\>](#constructorparameterst)\n      - [ReturnType\\\u003CT\\>](#returntypet)\n      - [InstanceType\\\u003CT\\>](#instancetypet)\n      - [ThisParameterType\\\u003CT\\>](#thisparametertypet)\n      - [OmitThisParameter\\\u003CT\\>](#omitthisparametert)\n      - [ThisType\\\u003CT\\>](#thistypet)\n      - [Uppercase\\\u003CT\\>](#uppercaset)\n      - [Lowercase\\\u003CT\\>](#lowercaset)\n      - [Capitalize\\\u003CT\\>](#capitalizet)\n      - [Uncapitalize\\\u003CT\\>](#uncapitalizet)\n      - [NoInfer\\\u003CT\\>](#noinfert)\n  - [Others](#others)\n    - [Errors and Exception Handling](#errors-and-exception-handling)\n    - [Mixin classes](#mixin-classes)\n    - [Asynchronous Language Features](#asynchronous-language-features)\n    - [Iterators and Generators](#iterators-and-generators)\n    - [TsDocs JSDoc Reference](#tsdocs-jsdoc-reference)\n    - [@types](#types)\n    - [JSX](#jsx-1)\n    - [ES6 Modules](#es6-modules)\n    - [ES7 Exponentiation Operator](#es7-exponentiation-operator)\n    - [The for-await-of Statement](#the-for-await-of-statement)\n    - [New target meta-property](#new-target-meta-property)\n    - [Dynamic Import Expressions](#dynamic-import-expressions)\n    - [\"tsc –watch\"](#tsc-watch)\n    - [Non-null Assertion Operator](#non-null-assertion-operator)\n    - [Defaulted declarations](#defaulted-declarations)\n    - [Optional Chaining](#optional-chaining)\n    - [Nullish coalescing operator](#nullish-coalescing-operator)\n    - [Template Literal Types](#template-literal-types)\n    - [Function overloading](#function-overloading)\n    - [Recursive Types](#recursive-types)\n    - [Recursive Conditional Types](#recursive-conditional-types)\n    - [ECMAScript Module Support in Node](#ecmascript-module-support-in-node)\n    - [Assertion Functions](#assertion-functions)\n    - [Variadic Tuple Types](#variadic-tuple-types)\n    - [Boxed types](#boxed-types)\n    - [Covariance and Contravariance in TypeScript](#covariance-and-contravariance-in-typescript)\n      - [Optional Variance Annotations for Type Parameters](#optional-variance-annotations-for-type-parameters)\n    - [Template String Pattern Index Signatures](#template-string-pattern-index-signatures)\n    - [The satisfies Operator](#the-satisfies-operator)\n    - [Type-Only Imports and Export](#type-only-imports-and-export)\n    - [using declaration and Explicit Resource Management](#using-declaration-and-explicit-resource-management)\n      - [await using declaration](#await-using-declaration)\n    - [Import Attributes](#import-attributes)\n    - [Regular Expression Syntax Checking](#regular-expression-syntax-checking)\n    - [import defer](#import-defer)\n\u003C!-- markdownlint-enable MD004 -->\n\n## Introduction\n\nWelcome to The Concise TypeScript Book! This guide equips you with essential knowledge and practical skills for effective TypeScript development. Discover key concepts and techniques to write clean, robust code. Whether you're a beginner or an experienced developer, this book serves as both a comprehensive guide and a handy reference for leveraging TypeScript's power in your projects.\n\nThis book covers TypeScript 6.0.\n\n## About the Author\n\nSimone Poggiali is an experienced Staff Engineer with a passion for writing professional-grade code since the 90s. Throughout his international career, he has contributed to numerous projects for a wide range of clients, from startups to large organizations. Notable companies such as HelloFresh, Siemens, O2, Leroy Merlin and Snowplow have benefited from his expertise and dedication.\n\nYou can reach Simone Poggiali on the following platforms:\n\n* LinkedIn: [https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fsimone-poggiali](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fsimone-poggiali)\n* GitHub: [https:\u002F\u002Fgithub.com\u002Fgibbok](https:\u002F\u002Fgithub.com\u002Fgibbok)\n* X.com: [https:\u002F\u002Fx.com\u002Fgibbok_coding](https:\u002F\u002Fx.com\u002Fgibbok_coding)\n* Email: gibbok.coding📧gmail.com\n\nFull list of contributors: [https:\u002F\u002Fgithub.com\u002Fgibbok\u002Ftypescript-book\u002Fgraphs\u002Fcontributors](https:\u002F\u002Fgithub.com\u002Fgibbok\u002Ftypescript-book\u002Fgraphs\u002Fcontributors)\n\n## TypeScript Introduction\n\n### What is TypeScript?\n\nTypeScript is a strongly typed programming language that builds on JavaScript. It was originally designed by Anders Hejlsberg in 2012 and is currently developed and maintained by Microsoft as an open source project.\n\nTypeScript compiles to JavaScript and can be executed in any JavaScript runtime (e.g., a browser or Node.js on a server).\n\nIt supports multiple programming paradigms such as functional, generic, imperative, and object-oriented programming, and is a compiled (transpiled) language that is converted into JavaScript before execution.\n\n### Why TypeScript?\n\nTypeScript is a strongly typed language that helps prevent common programming mistakes and avoid certain kinds of run-time errors before the program is executed.\n\nA strongly typed language allows the developer to specify various program constraints and behaviors in the data type definitions, facilitating the ability to verify the correctness of the software and prevent defects. This is especially valuable in large-scale applications.\n\nSome of the benefits of TypeScript:\n\n* Static typing, optionally strongly typed\n* Type Inference\n* Access to ES6 and ES7 features\n* Cross-Platform and Cross-browser Compatibility\n* Tooling support with IntelliSense\n\n### TypeScript and JavaScript\n\nTypeScript is written in `.ts` or `.tsx` files, while JavaScript files are written in `.js` or `.jsx`.\n\nFiles with the extension `.tsx` or `.jsx` can contain JavaScript Syntax Extension JSX, which is used in React for UI development.\n\nTypeScript is a typed superset of JavaScript (ECMAScript 2015) in terms of syntax. All JavaScript code is valid TypeScript code, but the reverse is not always true.\n\nFor instance, consider a function in a JavaScript file with the `.js` extension, such as the following:\n\n\u003C!-- skip -->\n```typescript\nconst sum = (a, b) => a + b;\n```\n\nThe function can be converted and used in TypeScript by changing the file extension to `.ts`. However, if the same function is annotated with TypeScript types, it cannot be executed in any JavaScript runtime without compilation. The following TypeScript code will produce a syntax error if it is not compiled:\n\n\u003C!-- skip -->\n```typescript\nconst sum = (a: number, b: number): number => a + b;\n```\n\nTypeScript was designed to detect possible exceptions that can occur at runtime during compilation time by having the developer define the intent with type annotations. In addition, TypeScript can also catch issues if no type annotation is provided. For instance, the following code snippet does not specify any TypeScript types:\n\n\u003C!-- skip -->\n```typescript\nconst items = [{ x: 1 }, { x: 2 }];\nconst result = items.filter(item => item.y);\n```\n\nIn this case, TypeScript detects an error and reports:\n\n```text\nProperty 'y' does not exist on type '{ x: number; }'.\n```\n\nTypeScript's type system is largely influenced by the runtime behavior of JavaScript. For example, the addition operator (+), which in JavaScript can either perform string concatenation or numeric addition, is modeled in the same way in TypeScript:\n\n```typescript\nconst result = '1' + 1; \u002F\u002F Result is of type string\n```\n\nThe team behind TypeScript has made a deliberate decision to flag unusual usage of JavaScript as errors. For instance, consider the following valid JavaScript code:\n\n\u003C!-- skip -->\n```typescript\nconst result = 1 + true; \u002F\u002F In JavaScript, the result is equal 2\n```\n\nHowever, TypeScript throws an error:\n\n```text\nOperator '+' cannot be applied to types 'number' and 'boolean'.\n```\n\nThis error occurs because TypeScript strictly enforces type compatibility, and in this case, it identifies an invalid operation between a number and a boolean.\n\n### TypeScript Code Generation\n\nThe TypeScript compiler has two main responsibilities: checking for type errors and compiling to JavaScript. These two processes are independent of each other. Types do not affect the execution of the code in a JavaScript runtime, as they are completely erased during compilation. TypeScript can still output JavaScript even in the presence of type errors.\nHere is an example of TypeScript code with a type error:\n\n\u003C!-- skip -->\n```typescript\nconst add = (a: number, b: number): number => a + b;\nconst result = add('x', 'y'); \u002F\u002F Argument of type 'string' is not assignable to parameter of type 'number'.\n```\n\nHowever, it can still produce executable JavaScript output:\n\n\u003C!-- skip -->\n```typescript\n'use strict';\nconst add = (a, b) => a + b;\nconst result = add('x', 'y'); \u002F\u002F xy\n```\n\nIt is not possible to check TypeScript types at runtime. For example:\n\n\u003C!-- skip -->\n```typescript\ninterface Animal {\n    name: string;\n}\ninterface Dog extends Animal {\n    bark: () => void;\n}\ninterface Cat extends Animal {\n    meow: () => void;\n}\nconst makeNoise = (animal: Animal) => {\n    if (animal instanceof Dog) {\n        \u002F\u002F 'Dog' only refers to a type, but is being used as a value here.\n        \u002F\u002F ...\n    }\n};\n```\n\nAs the types are erased after compilation, there is no way to run this code in JavaScript. To recognize types at runtime, we need to use another mechanism. TypeScript provides several options, with a common one being \"tagged union\". For example:\n\n```typescript\ninterface Dog {\n    kind: 'dog'; \u002F\u002F Tagged union\n    bark: () => void;\n}\ninterface Cat {\n    kind: 'cat'; \u002F\u002F Tagged union\n    meow: () => void;\n}\ntype Animal = Dog | Cat;\n\nconst makeNoise = (animal: Animal) => {\n    if (animal.kind === 'dog') {\n        animal.bark();\n    } else {\n        animal.meow();\n    }\n};\n\nconst dog: Dog = {\n    kind: 'dog',\n    bark: () => console.log('bark'),\n};\nmakeNoise(dog);\n```\n\nThe property \"kind\" is a value that can be used at runtime to distinguish between objects in JavaScript.\n\nIt is also possible for a value at runtime to have a type different from the one declared in the type declaration. For instance, if the developer has misinterpreted an API type and annotated it incorrectly.\n\nTypeScript is a superset of JavaScript, so the \"class\" keyword can be used as a type and value at runtime.\n\n```typescript\nclass Animal {\n    constructor(public name: string) {}\n}\nclass Dog extends Animal {\n    constructor(\n        public name: string,\n        public bark: () => void\n    ) {\n        super(name);\n    }\n}\nclass Cat extends Animal {\n    constructor(\n        public name: string,\n        public meow: () => void\n    ) {\n        super(name);\n    }\n}\ntype Mammal = Dog | Cat;\n\nconst makeNoise = (mammal: Mammal) => {\n    if (mammal instanceof Dog) {\n        mammal.bark();\n    } else {\n        mammal.meow();\n    }\n};\n\nconst dog = new Dog('Fido', () => console.log('bark'));\nmakeNoise(dog);\n```\n\nIn JavaScript, a \"class\" has a \"prototype\" property, and the \"instanceof\" operator can be used to test if the prototype property of a constructor appears anywhere in the prototype chain of an object.\n\nTypeScript has no effect on runtime performance, as all types will be erased. However, TypeScript does introduce some build time overhead.\n\n### Modern JavaScript Now (Downleveling)\n\nTypeScript can compile code to any released version of JavaScript since ECMAScript 3 (1999). This means that TypeScript can transpile code from the latest JavaScript features to older versions, a process known as Downleveling. This allows the usage of modern JavaScript while maintaining maximum compatibility with older runtime environments.\n\nIt's important to note that during transpilation to an older version of JavaScript, TypeScript may generate code that could incur a performance overhead compared to native implementations.\n\nHere are some of the modern JavaScript features that can be used in TypeScript:\n\n* ECMAScript modules instead of AMD-style \"define\" callbacks or CommonJS \"require\" statements.\n* Classes instead of prototypes.\n* Variables declaration using \"let\" or \"const\" instead of \"var\".\n* \"for-of\" loop or \".forEach\" instead of the traditional \"for\" loop.\n* Arrow functions instead of function expressions.\n* Destructuring assignment.\n* Shorthand property\u002Fmethod names and computed property names.\n* Default function parameters.\n\nBy leveraging these modern JavaScript features, developers can write more expressive and concise code in TypeScript.\n\n## Getting Started With TypeScript\n\n### Installation\n\nVisual Studio Code provides excellent support for the TypeScript language but does not include the TypeScript compiler. To install the TypeScript compiler, you can use a package manager like npm or yarn:\n\n```shell\nnpm install typescript --save-dev\n```\n\nor\n\n```shell\nyarn add typescript --dev\n```\n\nMake sure to commit the generated lockfile to ensure that every team member uses the same version of TypeScript.\n\nTo run the TypeScript compiler, you can use the following commands\n\n```shell\nnpx tsc\n```\n\nor\n\n```shell\nyarn tsc\n```\n\nIt is recommended to install TypeScript project-wise rather than globally, as it provides a more predictable build process. However, for one-off occasions, you can use the following command:\n\n```shell\nnpx tsc\n```\n\nor installing it globally:\n\n```shell\nnpm install -g typescript\n```\n\nIf you are using Microsoft Visual Studio, you can obtain TypeScript as a package in NuGet for your MSBuild projects. In the NuGet Package Manager Console, run the following command:\n\n```shell\nInstall-Package Microsoft.TypeScript.MSBuild\n```\n\nDuring the TypeScript installation, two executables are installed: \"tsc\" as the TypeScript compiler and \"tsserver\" as the TypeScript standalone server. The standalone server contains the compiler and language services that can be utilized by editors and IDEs to provide intelligent code completion.\n\nAdditionally, there are several TypeScript-compatible transpilers available, such as Babel (via a plugin) or swc. These transpilers can be used to convert TypeScript code into other target languages or versions.\n\n### Configuration\n\nTypeScript can be configured using the tsc CLI options or by utilizing a dedicated configuration file called tsconfig.json placed in the root of the project.\n\nTo generate a tsconfig.json file prepopulated with recommended settings, you can use the following command:\n\n```shell\ntsc --init\n```\n\nWhen executing the `tsc` command locally, TypeScript will compile the code using the configuration specified in the nearest tsconfig.json file.\n\nHere are some examples of CLI commands that run with the default settings:\n\n```shell\ntsc main.ts \u002F\u002F Compile a specific file (main.ts) to JavaScript\ntsc src\u002F*.ts \u002F\u002F Compile any .ts files under the 'src' folder to JavaScript\ntsc app.ts util.ts --outfile index.js \u002F\u002F Compile two TypeScript files (app.ts and util.ts) into a single JavaScript file (index.js)\n```\n\n### TypeScript Configuration File\n\nA tsconfig.json file is used to configure the TypeScript Compiler (tsc). Usually, it is added to the root of the project, together with the `package.json` file.\n\nNotes:\n\n* tsconfig.json accepts comments even if it is in json format.\n* It is advisable to use this configuration file instead of the command-line options.\n\nAt the following link you can find the complete documentation and its schema:\n\n[https:\u002F\u002Fwww.typescriptlang.org\u002Ftsconfig](https:\u002F\u002Fwww.typescriptlang.org\u002Ftsconfig)\n\n[https:\u002F\u002Fwww.typescriptlang.org\u002Ftsconfig\u002F](https:\u002F\u002Fwww.typescriptlang.org\u002Ftsconfig\u002F)\n\nThe following represents a list of the common and useful configurations:\n\n#### target\n\nThe \"target\" property is used to specify which version of JavaScript ECMAScript version your TypeScript should emit\u002Fcompile into. For modern browsers ES6 is a good option, for older browsers, ES5 is recommended. Note: ES5 support was removed in TypeScript 6.0.\n\n#### lib\n\nThe \"lib\" property is used to specify which library files to include at compilation time. TypeScript automatically includes APIs for features specified in the \"target\" property, but it is possible to omit or pick specific libraries for particular needs. For instance, if you are working on a server project, you could exclude the \"DOM\" library, which is useful only in a browser environment.\n\n#### strict\n\nThe \"strict\" option improves type safety by enabling stronger checks. It is enabled by default starting with TypeScript 6.0; otherwise, you should explicitly set it to true in your tsconfig.json. Enabling \"strict\" allows TypeScript to:\n\n* Emit code using \"use strict\" for each source file.\n* Consider \"null\" and \"undefined\" in the type checking process.\n* Disable the usage of the \"any\" type when no type annotations are present.\n* Raise an error on the usage of the \"this\" expression, which would otherwise imply the \"any\" type.\n\n#### module\n\nThe \"module\" property sets the module system supported for the compiled program. During runtime, a module loader is used to locate and execute dependencies based on the specified module system.\n\nThe most common module loaders used in JavaScript are Node.js CommonJS for server-side applications and RequireJS for AMD modules in browser-based web applications. TypeScript can emit code for various module systems, including UMD, System, ESNext, ES2015\u002FES6, and ES2020. The module system should be chosen based on the target environment and the module loading mechanism available in that environment.\n\nNote: Support for older module systems (AMD, UMD, SystemJS) was removed in TypeScript 6.0.\n\n#### moduleResolution\n\nThe \"moduleResolution\" property specifies the module resolution strategy. Use \"node\" for modern TypeScript code, the \"classic\" strategy is used only for old versions of TypeScript (before 1.6).\n\n#### esModuleInterop\n\nThe \"esModuleInterop\" property allows import default from CommonJS modules that did not export using the \"default\" property, this property provides a shim to ensure compatibility in the emitted JavaScript. After enabling this option we can use `import MyLibrary from \"my-library\"` instead of `import * as MyLibrary from \"my-library\"`.\n\n\"esModuleInterop\" was originally opt-in to avoid breaking changes, but have long been the recommended defaults. Disabling them can cause subtle runtime issues when using CommonJS with ESM. Note: Starting with TypeScript 6.0, this safer interop behavior is always enabled.\n\n#### jsx\n\nThe \"jsx\" property applies only to .tsx files used in ReactJS and controls how JSX constructs are compiled into JavaScript. A common option is \"preserve\" which will compile to a .jsx file keeping unchanged the JSX so it can be passed to different tools like Babel for further transformations.\n\n#### skipLibCheck\n\nThe \"skipLibCheck'' property will prevent TypeScript from type-checking the entire imported third-party packages. This property will reduce the compile time of a project. TypeScript will still check your code against the type definitions provided by these packages.\n\n#### files\n\nThe \"files\" property indicates to the compiler a list of files that must always be included in the program.\n\n#### include\n\n\u003C!-- markdownlint-disable MD049 -->\nThe \"include\" property indicates to the compiler a list of files that we would like to include. This property allows glob-like patterns, such as \"\\*_\" for any subdirectory, \"_\" for any file name, and \"?\" for optional characters.\n\u003C!-- markdownlint-enable MD049 -->\n\n#### exclude\n\nThe \"exclude\" property indicates to the compiler a list of files that should not be included in the compilation. This can include files such as \"node_modules\" or test files.\nNote: tsconfig.json allows comments.\n\n### importHelpers\n\nTypeScript uses helper code when generating code for certain advanced or down-leveled JavaScript features. By default, these helpers are duplicated in files using them. The `importHelpers` option imports these helpers from the `tslib` module instead, making the JavaScript output more efficient.\n\n### Migration to TypeScript Advice\n\nFor large projects, it is recommended to adopt a gradual transition where TypeScript and JavaScript code will initially coexist. Only small projects can be migrated to TypeScript in one go.\n\nThe first step of this transition is to introduce TypeScript into the build chain process. This can be done by using the \"allowJs\" compiler option, which permits .ts and .tsx files to coexist with existing JavaScript files. As TypeScript will fall back to a type of \"any\" for a variable when it cannot infer the type from JavaScript files, it is recommended to disable \"noImplicitAny\" in your compiler options at the beginning of the migration.\n\nThe second step is to ensure that your JavaScript tests work alongside TypeScript files so that you can run tests as you convert each module. If you are using Jest, consider using `ts-jest`, which allows you to test TypeScript projects with Jest.\n\nThe third step is to include type declarations for third-party libraries in your project. These declarations can be found either bundled or on DefinitelyTyped. You can search for them using [https:\u002F\u002Fwww.typescriptlang.org\u002Fdt\u002Fsearch](https:\u002F\u002Fwww.typescriptlang.org\u002Fdt\u002Fsearch) and install them using:\n\n```shell\nnpm install --save-dev @types\u002Fpackage-name\n```\n\nor\n\n```shell\nyarn add --dev @types\u002Fpackage-name\n```\n\nThe fourth step is to migrate module by module with a bottom-up approach, following your Dependency Graph starting with the leaves. The idea is to start converting Modules that do not depend on other Modules. To visualize the dependency graphs, you can use the \"madge\" tool.\n\nGood candidate modules for these initial conversions are utility functions and code related to external APIs or specifications. It is possible to automatically generate TypeScript type definitions from Swagger contracts, GraphQL or JSON schemas to be included in your project.\n\nWhen there are no specifications or official schemas available, you can generate types from raw data, such as JSON returned by a server. However, it is recommended to generate types from specifications instead of data to avoid missing edge cases.\n\nDuring the migration, refrain from code refactoring and focus only on adding types to your modules.\n\nThe fifth step is to enable \"noImplicitAny,\" which will enforce that all types are known and defined, providing a better TypeScript experience for your project.\n\nDuring the migration, you can use the `@ts-check` directive, which enables TypeScript type checking in a JavaScript file. This directive provides a loose version of type checking and can be initially used to identify issues in JavaScript files. When `@ts-check` is included in a file, TypeScript will try to deduce definitions using JSDoc-style comments. However, consider using JSDoc annotations only at a very early stage of the migration.\n\nConsider keeping the default value of `noEmitOnError` in your tsconfig.json as false. This will allow you to output JavaScript source code even if errors are reported.\n\n## Exploring the Type System\n\n### The TypeScript Language Service\n\nThe TypeScript Language Service, also known as tsserver, offers various features such as error reporting, diagnostics, compile-on-save, renaming, go to definition, completion lists, signature help, and more. It is primarily used by integrated development environments (IDEs) to provide IntelliSense support. It seamlessly integrates with Visual Studio Code and is utilized by tools like Conquer of Completion (Coc).\n\nDevelopers can leverage a dedicated API and create their own custom language service plugins to enhance the TypeScript editing experience. This can be particularly useful for implementing special linting features or enabling auto-completion for a custom templating language.\n\n\u003C!-- markdownlint-disable MD044 -->\nAn example of a real-world custom plugin is \"typescript-styled-plugin\", which provides syntax error reporting and IntelliSense support for CSS properties in styled components.\n\u003C!-- markdownlint-enable MD044 -->\n\nFor more information and quick start guides, you can refer to the official TypeScript Wiki on GitHub: [https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FTypeScript\u002Fwiki\u002F](https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FTypeScript\u002Fwiki\u002F)\n\n### Structural Typing\n\nTypeScript is based on a structural type system. This means that the compatibility and equivalence of types are determined by the type's actual structure or definition, rather than its name or place of declaration, as in nominative type systems like C# or C.\n\nTypeScript's structural type system was designed based on how JavaScript's dynamic duck typing system works during runtime.\n\nThe following example is valid TypeScript code. As you can observe, \"X\" and \"Y\" have the same member \"a,\" even though they have different declaration names. The types are determined by their structures, and in this case, since the structures are the same, they are compatible and valid.\n\n```typescript\ntype X = {\n    a: string;\n};\ntype Y = {\n    a: string;\n};\nconst x: X = { a: 'a' };\nconst y: Y = x; \u002F\u002F Valid\n```\n\n### TypeScript Fundamental Comparison Rules\n\nThe TypeScript comparison process is recursive and executed on types nested at any level.\n\nA type \"X\" is compatible with \"Y\" if \"Y\" has at least the same members as \"X\".\n\n```typescript\ntype X = {\n    a: string;\n};\nconst y = { a: 'A', b: 'B' }; \u002F\u002F Valid, as it has at least the same members as X\nconst r: X = y;\n```\n\nFunction parameters are compared by types, not by their names:\n\n```typescript\ntype X = (a: number) => void;\ntype Y = (a: number) => void;\nlet x: X = (j: number) => undefined;\nlet y: Y = (k: number) => undefined;\ny = x; \u002F\u002F Valid\nx = y; \u002F\u002F Valid\n```\n\nFunction return types must be the same:\n\n\u003C!-- skip -->\n```typescript\ntype X = (a: number) => undefined;\ntype Y = (a: number) => number;\nlet x: X = (a: number) => undefined;\nlet y: Y = (a: number) => 1;\ny = x; \u002F\u002F Invalid\nx = y; \u002F\u002F Invalid\n```\n\nThe return type of a source function must be a subtype of the return type of a target function:\n\n\u003C!-- skip -->\n```typescript\nlet x = () => ({ a: 'A' });\nlet y = () => ({ a: 'A', b: 'B' });\nx = y; \u002F\u002F Valid\ny = x; \u002F\u002F Invalid member b is missing\n```\n\nDiscarding function parameters is allowed, as it is a common practice in JavaScript, for instance using \"Array.prototype.map()\":\n\n```typescript\n[1, 2, 3].map((element, _index, _array) => element + 'x');\n```\n\nTherefore, the following type declarations are completely valid:\n\n```typescript\ntype X = (a: number) => undefined;\ntype Y = (a: number, b: number) => undefined;\nlet x: X = (a: number) => undefined;\nlet y: Y = (a: number) => undefined; \u002F\u002F Missing b parameter\ny = x; \u002F\u002F Valid\n```\n\nAny additional optional parameters of the source type are valid:\n\n```typescript\ntype X = (a: number, b?: number, c?: number) => undefined;\ntype Y = (a: number) => undefined;\nlet x: X = a => undefined;\nlet y: Y = a => undefined;\ny = x; \u002F\u002F Valid\nx = y; \u002F\u002FValid\n```\n\nAny optional parameters of the target type without corresponding parameters in the source type are valid and not an error:\n\n```typescript\ntype X = (a: number) => undefined;\ntype Y = (a: number, b?: number) => undefined;\nlet x: X = a => undefined;\nlet y: Y = a => undefined;\ny = x; \u002F\u002F Valid\nx = y; \u002F\u002F Valid\n```\n\nThe rest parameter is treated as an infinite series of optional parameters:\n\n```typescript\ntype X = (a: number, ...rest: number[]) => undefined;\nlet x: X = a => undefined; \u002F\u002Fvalid\n```\n\nFunctions with overloads are valid if the overload signature is compatible with its implementation signature:\n\n\u003C!-- skip -->\n```typescript\nfunction x(a: string): void;\nfunction x(a: string, b: number): void;\nfunction x(a: string, b?: number): void {\n    console.log(a, b);\n}\nx('a'); \u002F\u002F Valid\nx('a', 1); \u002F\u002F Valid\n\nfunction y(a: string): void; \u002F\u002F Invalid, not compatible with implementation signature\nfunction y(a: string, b: number): void;\nfunction y(a: string, b: number): void {\n    console.log(a, b);\n}\ny('a');\ny('a', 1);\n```\n\nFunction parameter comparison succeeds if the source and target parameters are assignable to supertypes or subtypes (bivariance).\n\n```typescript\n\u002F\u002F Supertype\nclass X {\n    a: string;\n    constructor(value: string) {\n        this.a = value;\n    }\n}\n\u002F\u002F Subtype\nclass Y extends X {}\n\u002F\u002F Subtype\nclass Z extends X {}\n\ntype GetA = (x: X) => string;\nconst getA: GetA = x => x.a;\n\n\u002F\u002F Bivariance does accept supertypes\nconsole.log(getA(new X('x'))); \u002F\u002F Valid\nconsole.log(getA(new Y('Y'))); \u002F\u002F Valid\nconsole.log(getA(new Z('z'))); \u002F\u002F Valid\n```\n\nEnums are comparable and valid with numbers and vice versa, but comparing Enum values from different Enum types is invalid.\n\n\u003C!-- skip -->\n```typescript\nenum X {\n    A,\n    B,\n}\nenum Y {\n    A,\n    B,\n    C,\n}\nconst xa: number = X.A; \u002F\u002F Valid\nconst ya: Y = 0; \u002F\u002F Valid\nX.A === Y.A; \u002F\u002F Invalid\n```\n\nInstances of a class are subject to a compatibility check for their private and protected members:\n\n\u003C!-- skip -->\n```typescript\nclass X {\n    public a: string;\n    constructor(value: string) {\n        this.a = value;\n    }\n}\n\nclass Y {\n    private a: string;\n    constructor(value: string) {\n        this.a = value;\n    }\n}\n\nlet x: X = new Y('y'); \u002F\u002F Invalid\n```\n\nThe comparison check does not take into consideration the different inheritance hierarchy, for instance:\n\n```typescript\nclass X {\n    public a: string;\n    constructor(value: string) {\n        this.a = value;\n    }\n}\nclass Y extends X {\n    public a: string;\n    constructor(value: string) {\n        super(value);\n        this.a = value;\n    }\n}\nclass Z {\n    public a: string;\n    constructor(value: string) {\n        this.a = value;\n    }\n}\nlet x: X = new X('x');\nlet y: Y = new Y('y');\nlet z: Z = new Z('z');\nx === y; \u002F\u002F Valid\nx === z; \u002F\u002F Valid even if z is from a different inheritance hierarchy\n```\n\nGenerics are compared using their structures based on the resulting type after applying the generic parameter, only the final result is compared as a non-generic type.\n\n\u003C!-- skip -->\n```typescript\ninterface X\u003CT> {\n    a: T;\n}\nlet x: X\u003Cnumber> = { a: 1 };\nlet y: X\u003Cstring> = { a: 'a' };\nx === y; \u002F\u002F Invalid as the type argument is used in the final structure\n```\n\n```typescript\ninterface X\u003CT> {}\nconst x: X\u003Cnumber> = 1;\nconst y: X\u003Cstring> = 'a';\nx === y; \u002F\u002F Valid as the type argument is not used in the final structure\n```\n\nWhen generics do not have their type argument specified, all the unspecified arguments are treated as types with \"any\":\n\n```typescript\ntype X = \u003CT>(x: T) => T;\ntype Y = \u003CK>(y: K) => K;\nlet x: X = x => x;\nlet y: Y = y => y;\nx = y; \u002F\u002F Valid\n```\n\nRemember:\n\n\u003C!-- skip -->\n```typescript\nlet a: number = 1;\nlet b: number = 2;\na = b; \u002F\u002F Valid, everything is assignable to itself\n\nlet c: any;\nc = 1; \u002F\u002F Valid, all types are assignable to any\n\nlet d: unknown;\nd = 1; \u002F\u002F Valid, all types are assignable to unknown\n\nlet e: unknown;\nlet e1: unknown = e; \u002F\u002F Valid, unknown is only assignable to itself and any\nlet e2: any = e; \u002F\u002F Valid\nlet e3: number = e; \u002F\u002F Invalid\n\nlet f: never;\nf = 1; \u002F\u002F Invalid, nothing is assignable to never\n\nlet g: void;\nlet g1: any;\ng = 1; \u002F\u002F Invalid, void is not assignable to or from anything expect any\ng = g1; \u002F\u002F Valid\n```\n\nPlease note that when \"strictNullChecks\" is enabled, \"null\" and \"undefined\" are treated similarly to \"void\"; otherwise, they are similar to \"never\".\n\n### Types as Sets\n\nIn TypeScript, a type is a set of possible values. This set is also referred to as the domain of the type. Each value of a type can be viewed as an element in a set. A type establishes the constraints that every element in the set must satisfy to be considered a member of that set.\nThe primary task of TypeScript is to check and verify whether one set is a subset of another.\n\nTypeScript supports various types of sets:\n\n| Set term           | TypeScript                      | Notes                                                                                                              |\n| ------------------ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------ |\n| Empty set          | never                           | \"never\" contains anything apart itself                                                                             |\n| Single element set | undefined \u002F null \u002F literal type |                                                                                                                    |\n| Finite set         | boolean \u002F union                 |                                                                                                                    |\n| Infinite set       | string \u002F number \u002F object        |                                                                                                                    |\n| Universal set      | any \u002F unknown                   | Every element is a member of \"any\" and every set is a subset of it \u002F \"unknown\" is a type-safe counterpart of \"any\" |\n\nHere few examples:\n\n| TypeScript            | Set term               | Example                                                                         |\n| --------------------- | ---------------------- | ------------------------------------------------------------------------------- |\n| never                 | ∅ (empty set)          | const x: never = 'x'; \u002F\u002F Error: Type 'string' is not assignable to type 'never' |\n|                       |                        |\n| Literal type          | Single element set     | type X = 'X';                                                                   |\n|                       |                        | type Y = 7;                                                                     |\n|                       |                        |\n| Value assignable to T | Value ∈ T (member of)  | type XY = 'X' \\| 'Y';                                                           |\n|                       |                        | const x: XY = 'X';                                                              |\n|                       |                        |\n| T1 assignable to T2   | T1 ⊆ T2 (subset of)    | type XY = 'X' \\| 'Y';                                                           |\n|                       |                        | const x: XY = 'X';                                                              |\n|                       |                        | const j: XY = 'J'; \u002F\u002F Type '\"J\"' is not assignable to type 'XY'.                |\n|                       |                        |                                                                                 |\n| T1 extends T2         | T1 ⊆ T2 (subset of)    | type X = 'X' extends string ? true : false;                                     |\n|                       |                        |\n| T1 \\| T2              | T1 ∪ T2 (union)        | type XY = 'X' \\| 'Y';                                                           |\n|                       |                        | type JK = 1 \\| 2;                                                               |\n|                       |                        |\n| T1 & T2               | T1 ∩ T2 (intersection) | type X = \\{ a: string \\}                                                          |\n|                       |                        | type Y = \\{ b: string \\}                                                          |\n|                       |                        | type XY = X & Y                                                                 |\n|                       |                        | const x: XY = \\{ a: 'a', b: 'b' \\}                                                |\n|                       |                        |\n| unknown               | Universal set          | const x: unknown = 1                                                            |\n\nAn union, (T1 | T2) creates a wider set (both):\n\n```typescript\ntype X = {\n    a: string;\n};\ntype Y = {\n    b: string;\n};\ntype XY = X | Y;\nconst r: XY = { a: 'a', b: 'x' }; \u002F\u002F Valid\n```\n\nAn intersection, (T1 & T2) create a narrower set (only shared):\n\n\u003C!-- skip -->\n```typescript\ntype X = {\n    a: string;\n};\ntype Y = {\n    a: string;\n    b: string;\n};\ntype XY = X & Y;\nconst r: XY = { a: 'a' }; \u002F\u002F Invalid\nconst j: XY = { a: 'a', b: 'b' }; \u002F\u002F Valid\n```\n\nThe `extends` keyword could be considered as a \"subset of\" in this context. It sets a constraint for a type. The extends used with a generic, take the generic as an infinite set and it will constrain it to a more specific type.\nPlease note that `extends` has nothing to do with hierarchy in a OOP sense (there is no this concept in TypeScript).\nTypeScript works with sets and does not have a strict hierarchy, infact, as in the example below, two types could overlap without either being a subtype of the other type (TypeScript considers the structure, shape of the objects).\n\n```typescript\ninterface X {\n    a: string;\n}\ninterface Y extends X {\n    b: string;\n}\ninterface Z extends Y {\n    c: string;\n}\nconst z: Z = { a: 'a', b: 'b', c: 'c' };\ninterface X1 {\n    a: string;\n}\ninterface Y1 {\n    a: string;\n    b: string;\n}\ninterface Z1 {\n    a: string;\n    b: string;\n    c: string;\n}\nconst z1: Z1 = { a: 'a', b: 'b', c: 'c' };\n\nconst r: Z1 = z; \u002F\u002F Valid\n```\n\n### Assign a type: Type Declarations and Type Assertions\n\nA type can be assigned in different ways in TypeScript:\n\n#### Type Declaration\n\nIn the following example, we use x: X (\": Type\") to declare a type for the variable x.\n\n```typescript\ntype X = {\n    a: string;\n};\n\n\u002F\u002F Type declaration\nconst x: X = {\n    a: 'a',\n};\n```\n\nIf the variable is not in the specified format, TypeScript will report an error. For instance:\n\n\u003C!-- skip -->\n```typescript\ntype X = {\n    a: string;\n};\n\nconst x: X = {\n    a: 'a',\n    b: 'b', \u002F\u002F Error: Object literal may only specify known properties\n};\n```\n\n#### Type Assertion\n\nIt is possible to add an assertion by using the `as` keyword. This tells the compiler that the developer has more information about a type and silences any errors that may occur.\n\nFor example:\n\n```typescript\ntype X = {\n    a: string;\n};\nconst x = {\n    a: 'a',\n    b: 'b',\n} as X;\n```\n\nIn the above example, the object x is asserted to have the type X using the as keyword. This informs the TypeScript compiler that the object conforms to the specified type, even though it has an additional property b not present in the type definition.\n\nType assertions are useful in situations where a more specific type needs to be specified, especially when working with the DOM. For instance:\n\n```typescript\nconst myInput = document.getElementById('my_input') as HTMLInputElement;\n```\n\nHere, the type assertion as HTMLInputElement is used to tell TypeScript that the result of getElementById should be treated as an HTMLInputElement.\nType assertions can also be used to remap keys, as shown in the example below with template literals:\n\n```typescript\ntype J\u003CType> = {\n    [Property in keyof Type as `prefix_${string &\n        Property}`]: () => Type[Property];\n};\ntype X = {\n    a: string;\n    b: number;\n};\ntype Y = J\u003CX>;\n```\n\nIn this example, the type `J\u003CType>` uses a mapped type with a template literal to remap the keys of Type. It creates new properties with a \"prefix_\" added to each key, and their corresponding values are functions returning the original property values.\n\nIt is worth noting that when using a type assertion, TypeScript will not execute excess property checking. Therefore, it is generally preferable to use a Type Declaration when the structure of the object is known in advance.\n\n#### Ambient Declarations\n\nAmbient declarations are files that describe types for JavaScript code, they have a file name format as `.d.ts.`. They are usually imported and used to annotate existing JavaScript libraries or to add types to existing JS files in your project.\n\nMany common libraries types can be found at:\n[https:\u002F\u002Fgithub.com\u002FDefinitelyTyped\u002FDefinitelyTyped\u002F](https:\u002F\u002Fgithub.com\u002FDefinitelyTyped\u002FDefinitelyTyped\u002F)\n\nand can be installed using:\n\n```shell\nnpm install --save-dev @types\u002Flibrary-name\n```\n\nFor your defined Ambient Declarations, you can import using the \"triple-slash\" reference:\n\n\u003C!-- skip -->\n```typescript\n\u002F\u002F\u002F \u003Creference path=\".\u002Flibrary-types.d.ts\" \u002F>\n```\n\nYou can use Ambient Declarations even within JavaScript files using `\u002F\u002F @ts-check`.\n\nThe `declare` keyword enables type definitions for existing JavaScript code without importing it, serving as a placeholder for types from another file or globally.\n\n### Property Checking and Excess Property Checking\n\nTypeScript is based on a structural type system but excess property checking is a property of TypeScript which allows it to check whether an object has the exact properties specified in the type.\n\nExcess Property Checking is performed when assigning object literals to variables or when passing them as arguments to the function's excess property, for instance.\n\n\u003C!-- skip -->\n```typescript\ntype X = {\n    a: string;\n};\nconst y = { a: 'a', b: 'b' };\nconst x: X = y; \u002F\u002F Valid because structural typing\nconst w: X = { a: 'a', b: 'b' }; \u002F\u002F Invalid because excess property checking\n```\n\n### Weak Types\n\nA type is considered weak when it contains nothing but a set of all-optional properties:\n\n```typescript\ntype X = {\n    a?: string;\n    b?: string;\n};\n```\n\nTypeScript considers an error to assign anything to a weak type when there is no overlap, for instance, the following throws an error:\n\n\u003C!-- skip -->\n```typescript\ntype Options = {\n    a?: string;\n    b?: string;\n};\n\nconst fn = (options: Options) => undefined;\n\nfn({ c: 'c' }); \u002F\u002F Invalid\n```\n\nAlthough not recommended, if needed, it is possible to bypass this check by using type assertion:\n\n```typescript\ntype Options = {\n    a?: string;\n    b?: string;\n};\nconst fn = (options: Options) => undefined;\nfn({ c: 'c' } as Options); \u002F\u002F Valid\n```\n\nOr by adding `unknown` to the index signature to the weak type:\n\n```typescript\ntype Options = {\n    [prop: string]: unknown;\n    a?: string;\n    b?: string;\n};\n\nconst fn = (options: Options) => undefined;\nfn({ c: 'c' }); \u002F\u002F Valid\n```\n\n### Strict Object Literal Checking (Freshness)\n\nStrict object literal checking, sometimes referred to as \"freshness\", is a feature in TypeScript that helps catch excess or misspelled properties that would otherwise go unnoticed in normal structural type checks.\n\nWhen creating an object literal, the TypeScript compiler considers it \"fresh.\" If the object literal is assigned to a variable or passed as a parameter, TypeScript will throw an error if the object literal specifies properties that do not exist in the target type.\n\nHowever, \"freshness\" disappears when an object literal is widened or a type assertion is used.\n\nHere are some examples to illustrate:\n\n\u003C!-- skip -->\n```typescript\ntype X = { a: string };\ntype Y = { a: string; b: string };\n\nlet x: X;\nx = { a: 'a', b: 'b' }; \u002F\u002F Freshness check: Invalid assignment\nvar y: Y;\ny = { a: 'a', bx: 'bx' }; \u002F\u002F Freshness check: Invalid assignment\n\nconst fn = (x: X) => console.log(x.a);\n\nfn(x);\nfn(y); \u002F\u002F Widening: No errors, structurally type compatible\n\nfn({ a: 'a', bx: 'b' }); \u002F\u002F Freshness check: Invalid argument\n\nlet c: X = { a: 'a' };\nlet d: Y = { a: 'a', b: '' };\nc = d; \u002F\u002F Widening: No Freshness check\n```\n\n### Type Inference\n\nTypeScript can infer types when no annotation is provided during:\n\n* Variable initialization.\n* Member initialization.\n* Setting defaults for parameters.\n* Function return type.\n\nFor example:\n\n```typescript\nlet x = 'x'; \u002F\u002F The type inferred is string\n```\n\nThe TypeScript compiler analyzes the value or expression and determines its type based on the available information.\n\n### More Advanced Inferences\n\nWhen multiple expressions are used in type inference, TypeScript looks for the \"best common types.\" For instance:\n\n```typescript\nlet x = [1, 'x', 1, null]; \u002F\u002F The type inferred is: (string | number | null)[]\n```\n\nIf the compiler cannot find the best common types, it returns a union type. For example:\n\n```typescript\nlet x = [new RegExp('x'), new Date()]; \u002F\u002F Type inferred is: (RegExp | Date)[]\n```\n\nTypeScript utilizes \"contextual typing\" based on the variable's location to infer types. In the following example, the compiler knows that `e` is of type `MouseEvent` because of the `click` event type defined in the lib.d.ts file, which contains ambient declarations for various common JavaScript constructs and the DOM:\n\n```typescript\nwindow.addEventListener('click', function (e) {}); \u002F\u002F The inferred type of e is MouseEvent\n```\n\n### Type Widening\n\nType widening is the process in which TypeScript assigns a type to a variable initialized when no type annotation was provided. It allows narrow to wider types but not vice versa.\nIn the following example:\n\n\u003C!-- skip -->\n```typescript\nlet x = 'x'; \u002F\u002F TypeScript infers as string, a wide type\nlet y: 'y' | 'x' = 'y'; \u002F\u002F y types is a union of literal types\ny = x; \u002F\u002F Invalid Type 'string' is not assignable to type '\"x\" | \"y\"'.\n```\n\nTypeScript assigns `string` to `x` based on the single value provided during initialization (`x`), this is an example of widening.\n\nTypeScript provides ways to have control of the widening process, for instance using \"const\".\n\n### Const\n\nUsing the `const` keyword when declaring a variable results in a narrower type inference in TypeScript.\n\nFor example:\n\n```typescript\nconst x = 'x'; \u002F\u002F TypeScript infers the type of x as 'x', a narrower type\nlet y: 'y' | 'x' = 'y';\ny = x; \u002F\u002F Valid: The type of x is inferred as 'x'\n```\n\nBy using `const` to declare the variable x, its type is narrowed to the specific literal value 'x'. Since the type of x is narrowed, it can be assigned to the variable y without any error.\nThe reason the type can be inferred is because `const` variables cannot be reassigned, so their type can be narrowed down to a specific literal type, in this case, the literal type 'x'.\n\n#### Const Modifier on Type Parameters\n\nFrom version 5.0 of TypeScript, it is possible to specify the `const` attribute on a generic type parameter. This allows for inferring the most precise type possible. Let's see an example without using `const`:\n\n```typescript\nfunction identity\u003CT>(value: T) {\n    \u002F\u002F No const here\n    return value;\n}\nconst values = identity({ a: 'a', b: 'b' }); \u002F\u002F Type infered is: { a: string; b: string; }\n```\n\nAs you can see, the properties `a` and `b` are inferred with a type of `string`   .\n\nNow, let's see the difference with the `const` version:\n\n```typescript\nfunction identity\u003Cconst T>(value: T) {\n    \u002F\u002F Using const modifier on type parameters\n    return value;\n}\nconst values = identity({ a: 'a', b: 'b' }); \u002F\u002F Type infered is: { a: \"a\"; b: \"b\"; }\n```\n\nNow we can see that the properties `a` and `b` are inferred as `const`, so `a` and `b` are treated as string literals rather than just `string` types.\n\n#### Const assertion\n\nThis feature allows you to declare a variable with a more precise literal type based on its initialization value, signifying to the compiler that the value should be treated as an immutable literal. Here are a few examples:\n\nOn a single property:\n\n```typescript\nconst v = {\n    x: 3 as const,\n};\nv.x = 3;\n```\n\nOn an entire object:\n\n```typescript\nconst v = {\n    x: 1,\n    y: 2,\n} as const;\n```\n\nThis can be particularly useful when defining the type for a tuple:\n\n```typescript\nconst x = [1, 2, 3]; \u002F\u002F number[]\nconst y = [1, 2, 3] as const; \u002F\u002F Tuple of readonly [1, 2, 3]\n```\n\n### Explicit Type Annotation\n\nWe can be specific and pass a type, in the following example property `x` is of type `number`:\n\n```typescript\nconst v = {\n    x: 1, \u002F\u002F Inferred type: number (widening)\n};\nv.x = 3; \u002F\u002F Valid\n```\n\nWe can make the type annotation more specific by using a union of literal types:\n\n\u003C!-- skip -->\n```typescript\nconst v: { x: 1 | 2 | 3 } = {\n    x: 1, \u002F\u002F x is now a union of literal types: 1 | 2 | 3\n};\nv.x = 3; \u002F\u002F Valid\nv.x = 100; \u002F\u002F Invalid\n```\n\n### Type Narrowing\n\nType Narrowing is the process in TypeScript where a general type is narrowed down to a more specific type. This occurs when TypeScript analyzes the code and determines that certain conditions or operations can refine the type information.\n\nNarrowing types can occur in different ways, including:\n\n#### Conditions\n\nBy using conditional statements, such as `if` or `switch`, TypeScript can narrow down the type based on the outcome of the condition. For example:\n\n```typescript\nlet x: number | undefined = 10;\n\nif (x !== undefined) {\n    x += 100; \u002F\u002F The type is number, which had been narrowed by the condition\n}\n```\n\n#### Throwing or returning\n\nThrowing an error or returning early from a branch can be used to help TypeScript narrow down a type. For example:\n\n```typescript\nlet x: number | undefined = 10;\n\nif (x === undefined) {\n    throw 'error';\n}\nx += 100;\n```\n\nOther ways to narrow down types in TypeScript include:\n\n* `instanceof` operator: Used to check if an object is an instance of a specific class.\n* `in` operator: Used to check if a property exists in an object.\n* `typeof` operator: Used to check the type of a value at runtime.\n* Built-in functions like `Array.isArray()`: Used to check if a value is an array.\n\n#### Discriminated Union\n\nUsing a \"Discriminated Union\" is a pattern in TypeScript where an explicit \"tag\" is added to objects to distinguish between different types within a union. This pattern is also referred to as a \"tagged union.\" In the following example, the \"tag\" is represented by the property \"type\":\n\n```typescript\ntype A = { type: 'type_a'; value: number };\ntype B = { type: 'type_b'; value: string };\n\nconst x = (input: A | B): string | number => {\n    switch (input.type) {\n        case 'type_a':\n            return input.value + 100; \u002F\u002F type is A\n        case 'type_b':\n            return input.value + 'extra'; \u002F\u002F type is B\n    }\n};\n```\n\n#### User-Defined Type Guards\n\nIn cases where TypeScript is unable to determine a type, it is possible to write a helper function known as a \"user-defined type guard.\" In the following example, we will utilize a Type Predicate to narrow down the type after applying certain filtering:\n\n```typescript\nconst data = ['a', null, 'c', 'd', null, 'f'];\n\nconst r1 = data.filter(x => x != null); \u002F\u002F The type is (string | null)[], TypeScript was not able to infer the type properly\n\nconst isValid = (item: string | null): item is string => item !== null; \u002F\u002F Custom type guard\n\nconst r2 = data.filter(isValid); \u002F\u002F The type is fine now string[], by using the predicate type guard we were able to narrow the type\n```\n\n#### Switch-true narrowing\n\nTypeScript 5.3 adds switch-true narrowing, letting you replace messy if\u002Felse chains with switch (true) using boolean conditions. It improves readability and still narrows types. It’s similar to pattern matching, but simpler.\n\n```typescript\nfunction classify(x: unknown) {\n    switch (true) {\n        case typeof x === 'string':\n            return `\"${x.toUpperCase()}\"`;\n        case typeof x === 'number':\n            return x > 0 ? 'positive' : 'negative';\n        case Array.isArray(x):\n            return `[${x.length} items]`;\n        default:\n            return 'something else';\n    }\n}\n```\n\n## Primitive Types\n\nTypeScript supports 7 primitive types. A primitive data type refers to a type that is not an object and does not have any methods associated with it. In TypeScript, all primitive types are immutable, meaning their values cannot be changed once they are assigned.\n\n### string\n\nThe `string` primitive type stores textual data, and the value is always double or single-quoted.\n\n```typescript\nconst x: string = 'x';\nconst y: string = 'y';\n```\n\nStrings can span multiple lines if surrounded by the backtick (`) character:\n\n```typescript\nlet sentence: string = `xxx,\n   yyy`;\n```\n\n### boolean\n\nThe `boolean` data type in TypeScript stores a binary value, either `true` or `false`.\n\n```typescript\nconst isReady: boolean = true;\n```\n\n### number\n\nA `number` data type in TypeScript is represented with a 64-bit floating point value. A `number` type can represent integers and fractions.\nTypeScript also supports hexadecimal, binary, and octal, for instance:\n\n```typescript\nconst decimal: number = 10;\nconst hexadecimal: number = 0xa00d; \u002F\u002F Hexadecimal starts with 0x\nconst binary: number = 0b1010; \u002F\u002F Binary starts with 0b\nconst octal: number = 0o633; \u002F\u002F Octal starts with 0o\n```\n\n### bigInt\n\nA `bigInt` represents numeric values that are very large (253 – 1) and cannot be represented with a `number`.\n\nA `bigInt` can be created by calling the built-in function `BigInt()` or by adding `n` to the end of any integer numeric literal:\n\n```typescript\nconst x: bigint = BigInt(9007199254740991);\nconst y: bigint = 9007199254740991n;\n```\n\nNotes:\n\n* `bigInt` values cannot be mixed with `number` and cannot be used with built-in `Math`, they must be coerced to the same type.\n* `bigInt` values are available only if target configuration is ES2020 or higher.\n\n### Symbol\n\nSymbols are unique identifiers that can be used as property keys in objects to prevent naming conflicts.\n\n```typescript\ntype Obj = {\n    [sym: symbol]: number;\n};\n\nconst a = Symbol('a');\nconst b = Symbol('b');\nlet obj: Obj = {};\nobj[a] = 123;\nobj[b] = 456;\n\nconsole.log(obj[a]); \u002F\u002F 123\nconsole.log(obj[b]); \u002F\u002F 456\n```\n\n### null and undefined\n\n`null` and `undefined` types both represent no value or the absence of any value.\n\nThe `undefined` type means the value is not assigned or initialized or indicates an unintentional absence of value.\n\nThe `null` type means that we know that the field does not have a value, so value is unavailable, it indicates an intentional absence of value.\n\n### Array\n\nAn `array` is a data type that can store multiple values of the same type or not. It can be defined using the following syntax:\n\n```typescript\nconst x: string[] = ['a', 'b'];\nconst y: Array\u003Cstring> = ['a', 'b'];\nconst j: Array\u003Cstring | number> = ['a', 1, 'b', 2]; \u002F\u002F Union\n```\n\nTypeScript supports readonly arrays using the following syntax:\n\n\u003C!-- skip -->\n```typescript\nconst x: readonly string[] = ['a', 'b']; \u002F\u002F Readonly modifier\nconst y: ReadonlyArray\u003Cstring> = ['a', 'b'];\nconst j: ReadonlyArray\u003Cstring | number> = ['a', 1, 'b', 2];\nj.push('x'); \u002F\u002F Invalid\n```\n\nTypeScript supports tuple and readonly tuple:\n\n```typescript\nconst x: [string, number] = ['a', 1];\nconst y: readonly [string, number] = ['a', 1];\n```\n\n### any\n\nThe `any` data type represents literally \"any\" value, it is the default value when TypeScript cannot infer the type or is not specified.\n\nWhen using `any` TypeScript compiler skips the type checking so there is no type safety when `any` is being used. Generally do not use `any` to silence the compiler when an error occurs, instead focus on fixing the error as with using `any`  it is possible to break contracts and we lose the benefits of TypeScript autocomplete.\n\nThe `any` type could be useful during a gradual migration from JavaScript to TypeScript, as it can silence the compiler.\n\nFor new projects use TypeScript configuration `noImplicitAny` which enables TypeScript to issue errors where `any` is used or inferred.\n\nThe `any`type  is usually a source of errors which can mask real problems with your types. Avoid using it as much as possible.\n\n## Type Annotations\n\nOn variables declared using `var`, `let` and `const`, it is possible to optionally add a type:\n\n```typescript\nconst x: number = 1;\n```\n\nTypeScript does a good job of inferring types, especially when simple one, so these declarations in most cases are not necessary.\n\nOn functions is possible to add type annotations to parameters:\n\n```typescript\nfunction sum(a: number, b: number) {\n    return a + b;\n}\n```\n\nThe following is an example using a anonymous functions (so called lambda function):\n\n```typescript\nconst sum = (a: number, b: number) => a + b;\n```\n\nThese annotation can be avoided when a default value for a parameter is present:\n\n```typescript\nconst sum = (a = 10, b: number) => a + b;\n```\n\nReturn type annotations can be added to functions:\n\n```typescript\nconst sum = (a = 10, b: number): number => a + b;\n```\n\nThis is useful especially for  more complex functions as writing expliciting the return type before an implementation can help better think about the function.\n\nGenerally consider annotating type signatures but not the body local variables and add types always to object literals.\n\n## Optional Properties\n\nAn object can specify Op","《简洁的 TypeScript 书》是一本全面且精炼的 TypeScript 开发指南，旨在帮助开发者高效地掌握 TypeScript 的使用。该项目通过清晰易懂的方式讲解了 TypeScript 的强大类型系统及其它高级特性，适用于从初学者到有经验的开发者各个层次的学习需求。其核心优势在于内容详实、结构紧凑，并且完全免费开源，支持多种语言版本，便于全球范围内的读者学习。无论是希望快速入门 TypeScript 的新手，还是想要深入理解该语言特性的资深工程师，都能从中受益。此外，作者提供了在线阅读和下载选项，使得获取知识变得更加便捷。","2026-06-11 03:36:31","high_star"]