├── .gitignore
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── LICENSE
├── README.md
├── RUN_INSTRUCTIONS.md
├── chapters
├── chapter-1_Getting_Started_With_Typescript_4
│ ├── classDiagrams.ts
│ ├── computeFrequency.ts
│ ├── degToRad.ts
│ ├── duckTyping.js
│ ├── features.ts
│ ├── inputOutput.ts
│ ├── intro.ts
│ ├── jsUtils.js
│ ├── libraries.ts
│ ├── migrating.ts
│ ├── mul.test.ts
│ ├── mul.ts
│ ├── refactoring.ts
│ ├── removeDuplicateVars.ts
│ ├── structural.ts
│ └── tsconfig.json
├── chapter-2_Core_Principles_and_use_cases
│ ├── .gitkeep
│ ├── DOM
│ │ ├── index.d.ts
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── index.js.map
│ │ ├── index.ts
│ │ ├── tsconfig.json
│ │ └── tsconfig.tsbuildinfo
│ ├── advanced.ts
│ ├── deno
│ │ └── index.ts
│ ├── express
│ │ ├── app.ts
│ │ ├── container.ts
│ │ ├── health.controller.ts
│ │ └── server.ts
│ ├── node-error
│ │ └── index.ts
│ ├── oop.ts
│ ├── partial.ts
│ ├── react
│ │ ├── app.tsx
│ │ ├── index.html
│ │ ├── tsconfig.json
│ │ └── webpack.config.js
│ ├── tsconfig.json
│ ├── utility.ts
│ └── webpack
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── index.ts
│ │ ├── tsconfig.json
│ │ └── webpack.config.js
├── chapter-3_Creational_Design_Patterns
│ ├── .gitkeep
│ ├── AbstractFactory.test.ts
│ ├── AbstractFactory.ts
│ ├── FactoryMethod.test.ts
│ ├── FactoryMethod.ts
│ ├── FactoryMethodType.ts
│ ├── InversifySingleton.ts
│ ├── ModuleSingleton.ts
│ ├── ParametricSingleton.ts
│ ├── Prototype.test.ts
│ ├── Prototype.ts
│ ├── ProxyBuilder.ts
│ ├── UsersApiSingleton.ts
│ ├── WebsiteBuilder.test.ts
│ ├── WebsiteBuilder.ts
│ ├── singleton.test.ts
│ └── singleton.ts
├── chapter-4_Structural_Design_Patterns
│ ├── .gitkeep
│ ├── Adapter.test.ts
│ ├── Adapter.ts
│ ├── Bridge.ts
│ ├── Composite.ts
│ ├── Decorator.test.ts
│ ├── Decorator.ts
│ ├── EventCreator.ts
│ ├── Facade.ts
│ ├── FacadeExample.ts
│ ├── Flyweight.ts
│ ├── Proxy.es6.ts
│ └── Proxy.ts
├── chapter-5_Behavioral_Design_Patterns
│ ├── .gitkeep
│ ├── ChainOfResponsibility.test.ts
│ ├── ChainOfResponsibility.ts
│ ├── Command.ts
│ ├── Iterator.ts
│ ├── Mediator.ts
│ ├── Memento.ts
│ ├── Observer.ts
│ ├── State.test.ts
│ ├── State.ts
│ ├── StateButton.ts
│ ├── Strategy.ts
│ ├── TemplateMethod.ts
│ └── Visitor.ts
├── chapter-6_Functional_Programming_Concepts
│ ├── .gitkeep
│ ├── FirstClassCitizens.ts
│ ├── FunctionComposition.ts
│ ├── Immutability.ts
│ ├── Lens.ts
│ ├── Monad.ts
│ ├── Monocle.ts
│ ├── PureFunctions.ts
│ ├── Recursion.ts
│ ├── Referential.ts
│ ├── Transducer.ts
│ └── tempCodeRunnerFile.ts
├── chapter-7_Reactive_Programming_concepts
│ ├── .gitkeep
│ ├── Futures.ts
│ ├── Observables.ts
│ ├── Operators.ts
│ ├── Patterns.ts
│ ├── Promises.ts
│ └── example.ts
├── chapter-8_Best_practices
│ ├── .gitkeep
│ ├── DDD.ts
│ ├── PatternCombinations.ts
│ ├── SOLID.ts
│ └── Utilities.ts
├── chapter-9_Anti_patterns
│ ├── .gitkeep
│ ├── ClassesFatigue.ts
│ ├── LanguageIdioms.ts
│ ├── PermissiveTypes.ts
│ ├── RuntimeAssertions.ts
│ ├── TypeInference.ts
│ └── inference.ts
├── smoke.ts
└── tsconfig.json
├── example.txt
├── images
└── playground_code.png
├── jest.config.js
├── package-lock.json
├── package.json
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | pids
2 | logs
3 | results
4 | tmp
5 |
6 | # Coverage reports
7 | coverage
8 |
9 | # API keys and secrets
10 | .env
11 |
12 | # Dependency directory
13 | node_modules
14 | bower_components
15 |
16 | # Editors
17 | .idea
18 | *.iml
19 |
20 | # OS metadata
21 | .DS_Store
22 | Thumbs.db
23 |
24 | # Ignore built ts files
25 | dist/**/*
26 |
27 | # ignore yarn.lock
28 | yarn.lock
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible Node.js debug attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Run Smoke Test Program",
9 | "type": "node",
10 | "program": "${workspaceFolder}/dist/smoke.js",
11 | "request": "launch",
12 | "preLaunchTask": "npm: build"
13 | },
14 | {
15 | "type": "node",
16 | "request": "attach",
17 | "name": "Attach by Process ID",
18 | "processId": "${command:PickProcess}",
19 | "protocol": "inspector"
20 | },
21 | {
22 | "type": "node",
23 | "request": "launch",
24 | "name": "Run Code from Chapter 1",
25 | "program": "${workspaceFolder}/chapters/chapter-1_Getting_Started_With_Typescript_4/${input:programNameChapter1}",
26 | "preLaunchTask": "tsc: build Chapter 1",
27 | "outFiles": ["${workspaceFolder}/dist/**/*.js"],
28 | },
29 | {
30 | "type": "node",
31 | "request": "launch",
32 | "name": "Run Code from Chapter 2",
33 | "program": "${workspaceFolder}/chapters/chapter-2_Core_Principles_and_use_cases/${input:programNameChapter2}",
34 | "preLaunchTask": "tsc: build Chapter 2",
35 | "outFiles": ["${workspaceFolder}/dist/**/*.js"],
36 | },
37 | ],
38 | "inputs": [
39 | {
40 | "type": "pickString",
41 | "id": "programNameChapter1",
42 | "description": "What program you want to launch?",
43 | "options": [
44 | "intro.ts",
45 | "inputOutput.ts",
46 | "classDiagrams.ts",
47 | "computeFrequency.ts",
48 | "removeDuplicateVars.ts",
49 | "refactoring.ts",
50 | "libraries.ts",
51 | "features.ts"
52 | ],
53 | "default": "computeFrequency.ts"
54 | },
55 | {
56 | "type": "pickString",
57 | "id": "programNameChapter2",
58 | "description": "What program you want to launch?",
59 | "options": ["intro.ts"],
60 | "default": "intro.ts"
61 | },
62 | ]
63 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "js/ts.implicitProjectConfig.strictFunctionTypes": false
3 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "build",
9 | "group": {
10 | "kind": "build",
11 | "isDefault": true
12 | }
13 | },
14 | {
15 | "type": "typescript",
16 | "tsconfig": "chapters/chapter-1_Getting_Started_With_Typescript_4/tsconfig.json",
17 | "problemMatcher": [
18 | "$tsc"
19 | ],
20 | "group": "build",
21 | "label": "tsc: build Chapter 1"
22 | },
23 | {
24 | "type": "typescript",
25 | "tsconfig": "chapters/chapter-2_Core_Principles_and_use_cases/DOM/tsconfig.json",
26 | "problemMatcher": [
27 | "$tsc"
28 | ],
29 | "group": "build",
30 | "label": "tsc: build Chapter 2 HTML DOM Example"
31 | },
32 | {
33 | "type": "typescript",
34 | "tsconfig": "chapters/chapter-2_Core_Principles_and_use_cases/tsconfig.json",
35 | "problemMatcher": [
36 | "$tsc"
37 | ],
38 | "group": "build",
39 | "label": "tsc: build Chapter 2"
40 | },
41 | {
42 | "type": "shell",
43 | "command": "deno",
44 | "args": [ "run", "--allow-net=0.0.0.0:8000", "chapters/chapter-2_Core_Principles_and_use_cases/deno/index.ts"],
45 | "label": "tsc: run Chapter 2 Deno Example"
46 | },
47 | ],
48 | }
49 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Packt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # TypeScript 4 Design Patterns and Best Practices
5 |
6 |
7 |
8 | This is the code repository for [TypeScript 4 Design Patterns and Best Practices](https://www.packtpub.com/product/typescript-4-design-patterns-and-best-practices/9781800563421), published by Packt.
9 |
10 | **Discover effective techniques and design patterns for every programming task**
11 |
12 | ## What is this book about?
13 | TypeScript offers a rich type system that can be used to enhance the existing JavaScript code. This book will cover all the classical design patterns in TypeScript and their primary categories using practical examples and class diagrams for each of the design patterns.
14 |
15 | This book covers the following exciting features:
16 | * Understand the role of design patterns and their significance
17 | * Explore all significant design patterns within the context of TypeScript
18 | * Find out how design patterns differ from design concepts
19 | * Understand how to put the principles of design patterns into practice
20 | * Discover additional patterns that stem from functional and reactive programming
21 | * Recognize common gotchas and antipatterns when developing TypeScript applications and understand how to avoid them
22 |
23 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1800563426) today!
24 |
25 |
27 |
28 | ## Instructions and Navigations
29 | All of the code is organized into folders. For example, Chapter02.
30 |
31 | The code will look like the following:
32 | ```
33 | export class EventCreator implements EventSender {
34 | sendEvent(action: string): void {
35 | console.log("Event Created: ", action);
36 | }
37 | }
38 | ```
39 |
40 | **Following is what you need for this book:**
41 | If you're a developer looking to learn how to apply established design patterns to solve common programming problems instead of reinventing solutions, you'll find this book useful. You're not expected to have prior knowledge of design patterns. Basic TypeScript knowledge is all you need to get started with this book.
42 |
43 | With the following software and hardware list you can run all code files present in the book (Chapter 1-9).
44 | ### Software and Hardware List
45 | | Chapter | Software required | OS required |
46 | | -------- | ------------------------------------ | ----------------------------------- |
47 | | 1 - 9 | Visual Studio Code 1.49, Node.js 12.18.3, TypeScript 4.1 | Windows, Mac OS X, and Linux (Any) |
48 |
49 | We also provide a PDF file that has color images of the screenshots/diagrams used in this book. [Click here to download it](https://static.packt-cdn.com/downloads/9781800563421_ColorImages.pdf).
50 |
51 | ### Related products
52 | * Mastering TypeScript 3 - Third Edition [[Packt]](https://www.packtpub.com/product/mastering-typescript-3-third-edition/9781789536706?utm_source=github&utm_medium=repository&utm_campaign=9781789536706) [[Amazon]](https://www.amazon.com/dp/1789536707)
53 |
54 | * Advanced TypeScript 3 Programming Projects [[Packt]](https://www.packtpub.com/product/advanced-typescript-3-programming-projects/9781789133042?utm_source=github&utm_medium=repository&utm_campaign=9781789133042) [[Amazon]](https://www.amazon.com/dp/1789133041)
55 |
56 | ## Get to Know the Author
57 | **Theo Despoudis**
58 | lives in Ireland, where he works as a Software Engineer for WP Engine and as a part-time tech practitioner for Fixate. He is the co-author of The React Workshop and Advanced Go Programming in 7 Days, Dzone Core Member, and maintains some open source projects on GitHub. Theo is available for conference talks, independent consulting, and corporate training services opportunities.
59 | ### Download a free PDF
60 |
61 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
62 |
https://packt.link/free-ebook/9781800563421
--------------------------------------------------------------------------------
/RUN_INSTRUCTIONS.md:
--------------------------------------------------------------------------------
1 | # Typescript 4 Design Patterns and Best Practices
2 |
3 | This is the code repository for Typescript 4 Design Patterns and Best Practices, published by Packt.
4 |
5 | ## How to run the code examples?
6 |
7 | To be able to run the examples, you first need to install all the required dependencies using the following command:
8 |
9 | ```sh
10 | npm install
11 | ```
12 |
13 | We have configured a local version of `ts-node` and `Typescript` so you don't have to install globally.
14 |
15 | If you have compatible TypeScript compiler installed globally, you can just use the global `ts-node` command to run target code bundle.
16 |
17 | You can then run the `ts` npm task providing the relative path of the script:
18 |
19 | ```
20 | npm run ts -- chapters/smoke.ts
21 | > ts-node "chapters/smoke.ts"
22 | 1
23 | 2
24 | 3
25 | 4
26 | Hello
27 | 1
28 | ```
29 |
30 | Alternatiely you may want to build and run the compiled javascript from the `dist` folder:
31 |
32 | ```
33 | npm run build
34 | > npx tsc --build chapters
35 |
36 | node dist/smoke.js
37 | 1
38 | 2
39 | 3
40 | 4
41 | Hello
42 | 1
43 | ```
44 |
45 | In some cases you may want to quickly see the compiled javascript or to quickly test some examples using the [TypeScript Playground](https://www.typescriptlang.org/play/index.html). You can copy the code in the playground (left) to get the resulting JavaScript output (right)
46 |
47 | 
48 |
49 | ## Code examples
50 |
51 | - [Chapter 1: Getting Started With Typescript 4](./chapters/chapter-1_Getting_Started_With_Typescript_4/)
52 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/classDiagrams.ts:
--------------------------------------------------------------------------------
1 | interface Identifiable {
2 | id: T;
3 | }
4 |
5 | class Customer {}
6 |
7 | class Product implements Identifiable {
8 | id: string;
9 | constructor(id: string) {
10 | this.id = id;
11 | }
12 | }
13 |
14 | abstract class BaseAPIClient {}
15 |
16 | // Association
17 | class Blog implements Identifiable {
18 | id: string;
19 | authorId: string;
20 | constructor(id: string, authorId: string) {
21 | this.id = id;
22 | this.authorId = authorId;
23 | }
24 | }
25 |
26 | class Author {}
27 |
28 | // Aggregation
29 | class QueryBuilder {}
30 | class EmptyQueryBuilder extends QueryBuilder {}
31 |
32 | interface SearchParams {
33 | qb?: QueryBuilder;
34 | path: string;
35 | }
36 |
37 | class SearchService {
38 | queryBuilder?: QueryBuilder;
39 | path: string;
40 |
41 | constructor({ qb = EmptyQueryBuilder, path }: SearchParams) {
42 | this.queryBuilder = qb;
43 | this.path = path;
44 | }
45 | }
46 |
47 | // Composition
48 | class Directory {
49 | files: File[];
50 | directories: Directory[];
51 | constructor(files: File[], directories: Directory[]) {
52 | this.files = files;
53 | this.directories = directories;
54 | }
55 |
56 | addFile(file: File): void {
57 | this.files.push(file);
58 | }
59 | addDir(directory: Directory): void {
60 | this.directories.push(directory);
61 | }
62 | }
63 |
64 | // Visibility
65 | class SSHUser {
66 | private privateKey: string;
67 | public publicKey: string;
68 |
69 | constructor(prvKey: string, pubKey: string) {
70 | this.privateKey = prvKey;
71 | this.publicKey = pubKey;
72 | }
73 |
74 | public getBase64(): string {
75 | return Buffer.from(this.publicKey).toString("base64");
76 | }
77 | }
78 |
79 | // Inheritance
80 |
81 | class BaseClient {}
82 | class UsersApiClient extends BaseClient {}
83 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/computeFrequency.ts:
--------------------------------------------------------------------------------
1 | function computeFrequency(input: string) {
2 | const freqTable = new Map();
3 | for (let ch of input) {
4 | if (!freqTable.has(ch)) {
5 | freqTable.set(ch, 1);
6 | } else {
7 | freqTable.set(ch, freqTable.get(ch) + 1);
8 | }
9 | }
10 |
11 | return freqTable;
12 | }
13 |
14 | console.log(computeFrequency("12345"));
15 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/degToRad.ts:
--------------------------------------------------------------------------------
1 | const degToRad = (degree): number => (degree * Math.PI) / 180;
2 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/duckTyping.js:
--------------------------------------------------------------------------------
1 | export function triggerNotification(emailClient, logger) {
2 | if (logger && typeof logger.log === "function") {
3 | logger.log("Sending email");
4 | }
5 | if (emailClient && typeof emailClient.send === "function") {
6 | emailClient.send("Message Sent");
7 | }
8 | }
9 |
10 | triggerNotification(
11 | { log: () => console.log("Logger call") },
12 | { send: (msg) => console.log(msg) }
13 | ); // Nothing!
14 | triggerNotification(
15 | { send: (msg) => console.log(msg) },
16 | { log: () => console.log("Logger call") }
17 | ); // Works!
18 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/features.ts:
--------------------------------------------------------------------------------
1 | type Point2d = [number, number];
2 | type Point3d = [number, number, number];
3 |
4 | const point1: Point2d = [1, 2];
5 | const point2: Point3d = [1, 2, 3];
6 |
7 | type NamedType = [string, ...T];
8 | type NamedPoint2d = NamedType;
9 |
10 | const point3: NamedPoint2d = ["Point: (1, 2)", 1, 2];
11 |
12 | type Point2dL = [x: number, y: number];
13 | type Point3dL = [x: number, y: number, z: number];
14 |
15 | type Suit = `${"Spade" | "Heart" | "Diamond" | "Club"}`;
16 | type Rank = `${
17 | | "2"
18 | | "3"
19 | | "4"
20 | | "5"
21 | | "6"
22 | | "7"
23 | | "8"
24 | | "9"
25 | | "10"
26 | | "Jack"
27 | | "Queen"
28 | | "King"
29 | | "Ace"}`;
30 |
31 | type Deck = `${Rank} of ${Suit}`;
32 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/inputOutput.ts:
--------------------------------------------------------------------------------
1 | const stream = process.stdin;
2 | setImmediate(function () {
3 | stream.push(null);
4 | });
5 |
6 | stream.pipe(process.stdout);
7 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/intro.ts:
--------------------------------------------------------------------------------
1 | const one: string = "one";
2 | const two: boolean = false;
3 | const three: number = 3;
4 | const four: null = null;
5 | const five: unknown = 5;
6 | const six: any = 6;
7 | const seven: unique symbol = Symbol("seven");
8 | let eight: never; // note that const eight: never cannot happen as we cannot instantiate a never
9 | let nine: bigint = BigInt(8);
10 |
11 | enum Keys {
12 | Up,
13 | Down,
14 | Left,
15 | Right,
16 | }
17 | let up: Keys = Keys.Up;
18 |
19 | const enum Bool {
20 | True,
21 | False,
22 | }
23 |
24 | let truth: Bool = Bool.True;
25 |
26 | const arr: number[] = [1, 2, 3]; // array of numbers of any size
27 | const tup: [number] = [1];
28 |
29 | class User {
30 | private name: string;
31 | constructor(name: string) {
32 | this.name = name;
33 | }
34 |
35 | public getName(): string {
36 | return this.name;
37 | }
38 | }
39 |
40 | const user = new User("Theo");
41 | console.log(user.getName());
42 |
43 | abstract class BaseApiClient {
44 | abstract fetch(req: any): Promise; // must be implemented in sub-classes
45 | }
46 |
47 | class UsersClient extends BaseApiClient {
48 | fetch(req: any): Promise {
49 | return Promise.resolve([]);
50 | }
51 | }
52 |
53 | const client = new UsersClient();
54 | client.fetch({ url: "/users" });
55 |
56 | interface Comparable {
57 | compareTo(o: T): number;
58 | }
59 |
60 | interface AppConfig {
61 | paths: {
62 | base: string;
63 | };
64 | maxRetryCount?: number;
65 | }
66 |
67 | const appConfig: AppConfig = {
68 | paths: {
69 | base: "/",
70 | },
71 | };
72 |
73 | type A = "A";
74 | type B = "B";
75 |
76 | type C = A & B; // type is never
77 | type D = C | "E"; // type is "E"
78 | type E = {
79 | name: string;
80 | };
81 |
82 | type F = E & {
83 | age: number;
84 | };
85 |
86 | let e: F = {
87 | name: "Theo",
88 | age: 20,
89 | };
90 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/jsUtils.js:
--------------------------------------------------------------------------------
1 | const isObject = (o) => {
2 | return o === Object(o) && !isArray(o) && typeof o !== "function";
3 | };
4 |
5 | const isArray = (arr) => {
6 | return Array.isArray(a);
7 | };
8 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/libraries.ts:
--------------------------------------------------------------------------------
1 | import "reflect-metadata";
2 | import { Container, injectable, inject } from "inversify";
3 |
4 | @injectable()
5 | class LoggerService {
6 | public logRequest() {
7 | console.log("call API Request");
8 | }
9 | }
10 |
11 | @injectable()
12 | class ApiService {
13 | private logger: LoggerService;
14 |
15 | public constructor(logger: LoggerService) {
16 | this.logger = logger;
17 | }
18 |
19 | public request() {
20 | this.logger.logRequest();
21 | return Promise.resolve([]);
22 | }
23 | }
24 |
25 | var container = new Container();
26 | container.bind(LoggerService).to(LoggerService);
27 | container.bind(ApiService).to(ApiService);
28 |
29 | const apiService = container.resolve(ApiService);
30 | apiService.request();
31 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/migrating.ts:
--------------------------------------------------------------------------------
1 | import { triggerNotification } from "./duckTyping";
2 | const isObject = require("./jsUtils");
3 |
4 | triggerNotification(
5 | { send: (msg) => console.log(msg) },
6 | { log: () => console.log("Logger call") }
7 | );
8 |
9 | isObject([]);
10 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/mul.test.ts:
--------------------------------------------------------------------------------
1 | import mul from "./mul";
2 |
3 | test("multiplies 2 and 3 to give 12", () => {
4 | expect(mul(2, 3)).toBe(6);
5 | });
6 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/mul.ts:
--------------------------------------------------------------------------------
1 | function mul(a: number, b: number) {
2 | return a * b;
3 | }
4 |
5 | export default mul;
6 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/refactoring.ts:
--------------------------------------------------------------------------------
1 | function find(arr: T[], predicate: (item: T) => boolean) {
2 | for (let item of arr) {
3 | if (predicate(item)) {
4 | return item;
5 | }
6 | }
7 | return undefined;
8 | }
9 |
10 | function indexOf(arr: T[], predicate: (item: T) => boolean) {
11 | for (let i = 0; i < arr.length; i += 1) {
12 | if (predicate(arr[i])) {
13 | return i;
14 | }
15 | }
16 | return -1;
17 | }
18 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/removeDuplicateVars.ts:
--------------------------------------------------------------------------------
1 | function removeDuplicateChars(input: string) {
2 | const result: string[] = [];
3 | //const result = ["a"];
4 | let seen = new Set();
5 | for (let c of input) {
6 | if (!seen.has(c)) {
7 | seen.add(c);
8 | result.push(c);
9 | }
10 | }
11 | }
12 |
13 | console.log(removeDuplicateChars("aarfqwevzxcddd"));
14 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/structural.ts:
--------------------------------------------------------------------------------
1 | interface Logger {
2 | log: (msg: string) => void;
3 | }
4 |
5 | let logger: Logger;
6 | let cat = { log: (msg: string) => console.log(msg) };
7 | logger = cat;
8 |
--------------------------------------------------------------------------------
/chapters/chapter-1_Getting_Started_With_Typescript_4/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | // compiler options
5 | "composite": true,
6 | "allowJs": true,
7 | "noImplicitAny": true
8 | }
9 | }
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/TypeScript-4-Design-Patterns-and-Best-Practices/794888bd4c351b9565e01828440e3d0cf06d26c6/chapters/chapter-2_Core_Principles_and_use_cases/.gitkeep
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/DOM/index.d.ts:
--------------------------------------------------------------------------------
1 | declare const p: Element;
2 | declare const span: HTMLSpanElement;
3 | declare const button: HTMLButtonElement | null;
4 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/DOM/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Document
5 |
6 |
7 |
8 | Typescript 4 Design Patterns
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/DOM/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var p = document.getElementsByClassName("paragraph")[0];
3 | var span = document.createElement("span");
4 | span.textContent = "This is a text we added dynamically";
5 | p === null || p === void 0 ? void 0 : p.appendChild(span);
6 | var button = document.querySelector("button");
7 | button === null || button === void 0 ? void 0 : button.addEventListener("click", function () {
8 | window.alert("You Clicked the Submit Button");
9 | });
10 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/DOM/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";AAAA,IAAM,CAAC,GAAG,QAAQ,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAE1D,IAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;AAC5C,IAAI,CAAC,WAAW,GAAG,qCAAqC,CAAC;AACzD,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,WAAW,CAAC,IAAI,EAAE;AAErB,IAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;AAChD,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,gBAAgB,CAAC,OAAO,EAAE;IAChC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;AAChD,CAAC,EAAE"}
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/DOM/index.ts:
--------------------------------------------------------------------------------
1 | const p = document.getElementsByClassName("paragraph")[0];
2 |
3 | const spanArea = document.createElement("span");
4 | spanArea.textContent = "This is a text we added dynamically";
5 | p?.appendChild(spanArea);
6 |
7 | const actionButton = document.querySelector("button");
8 | actionButton?.addEventListener("click", () => {
9 | window.alert("You Clicked the Submit Button");
10 | });
11 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/DOM/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../../tsconfig.json",
3 |
4 | "compilerOptions": {
5 | "lib": ["DOM"],
6 | // compiler options
7 | "composite": true,
8 | "noImplicitAny": false,
9 | "outDir": "./"
10 | }
11 | }
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/DOM/tsconfig.tsbuildinfo:
--------------------------------------------------------------------------------
1 | {
2 | "program": {
3 | "fileInfos": {
4 | "../../node_modules/typescript/lib/lib.es5.d.ts": {
5 | "version": "9622e8bd7cc72a7dab819a8011ecbf81d443638082e5cb99ecf2e75ff56ffc9d",
6 | "signature": "9622e8bd7cc72a7dab819a8011ecbf81d443638082e5cb99ecf2e75ff56ffc9d",
7 | "affectsGlobalScope": true
8 | },
9 | "../../node_modules/typescript/lib/lib.es2015.d.ts": {
10 | "version": "dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6",
11 | "signature": "dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6",
12 | "affectsGlobalScope": false
13 | },
14 | "../../node_modules/typescript/lib/lib.es2016.d.ts": {
15 | "version": "7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467",
16 | "signature": "7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467",
17 | "affectsGlobalScope": false
18 | },
19 | "../../node_modules/typescript/lib/lib.es2017.d.ts": {
20 | "version": "8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9",
21 | "signature": "8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9",
22 | "affectsGlobalScope": false
23 | },
24 | "../../node_modules/typescript/lib/lib.es2018.d.ts": {
25 | "version": "5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06",
26 | "signature": "5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06",
27 | "affectsGlobalScope": false
28 | },
29 | "../../node_modules/typescript/lib/lib.dom.d.ts": {
30 | "version": "abadddbf660adeec27e9a56584907d52fa1d6e1e1dc49f639a921baa951b7a84",
31 | "signature": "abadddbf660adeec27e9a56584907d52fa1d6e1e1dc49f639a921baa951b7a84",
32 | "affectsGlobalScope": true
33 | },
34 | "../../node_modules/typescript/lib/lib.es2015.core.d.ts": {
35 | "version": "46ee15e9fefa913333b61eaf6b18885900b139867d89832a515059b62cf16a17",
36 | "signature": "46ee15e9fefa913333b61eaf6b18885900b139867d89832a515059b62cf16a17",
37 | "affectsGlobalScope": true
38 | },
39 | "../../node_modules/typescript/lib/lib.es2015.collection.d.ts": {
40 | "version": "43fb1d932e4966a39a41b464a12a81899d9ae5f2c829063f5571b6b87e6d2f9c",
41 | "signature": "43fb1d932e4966a39a41b464a12a81899d9ae5f2c829063f5571b6b87e6d2f9c",
42 | "affectsGlobalScope": true
43 | },
44 | "../../node_modules/typescript/lib/lib.es2015.generator.d.ts": {
45 | "version": "cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a",
46 | "signature": "cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a",
47 | "affectsGlobalScope": true
48 | },
49 | "../../node_modules/typescript/lib/lib.es2015.iterable.d.ts": {
50 | "version": "8b2a5df1ce95f78f6b74f1a555ccdb6baab0486b42d8345e0871dd82811f9b9a",
51 | "signature": "8b2a5df1ce95f78f6b74f1a555ccdb6baab0486b42d8345e0871dd82811f9b9a",
52 | "affectsGlobalScope": true
53 | },
54 | "../../node_modules/typescript/lib/lib.es2015.promise.d.ts": {
55 | "version": "2bb4b3927299434052b37851a47bf5c39764f2ba88a888a107b32262e9292b7c",
56 | "signature": "2bb4b3927299434052b37851a47bf5c39764f2ba88a888a107b32262e9292b7c",
57 | "affectsGlobalScope": true
58 | },
59 | "../../node_modules/typescript/lib/lib.es2015.proxy.d.ts": {
60 | "version": "7207e317a2cb07a177e7d963ab7b8c0e85dde7f9ddb50351f830239bf597569e",
61 | "signature": "7207e317a2cb07a177e7d963ab7b8c0e85dde7f9ddb50351f830239bf597569e",
62 | "affectsGlobalScope": true
63 | },
64 | "../../node_modules/typescript/lib/lib.es2015.reflect.d.ts": {
65 | "version": "cb609802a8698aa28b9c56331d4b53f590ca3c1c3a255350304ae3d06017779d",
66 | "signature": "cb609802a8698aa28b9c56331d4b53f590ca3c1c3a255350304ae3d06017779d",
67 | "affectsGlobalScope": true
68 | },
69 | "../../node_modules/typescript/lib/lib.es2015.symbol.d.ts": {
70 | "version": "3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93",
71 | "signature": "3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93",
72 | "affectsGlobalScope": true
73 | },
74 | "../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts": {
75 | "version": "9d122b7e8c1a5c72506eea50c0973cba55b92b5532d5cafa8a6ce2c547d57551",
76 | "signature": "9d122b7e8c1a5c72506eea50c0973cba55b92b5532d5cafa8a6ce2c547d57551",
77 | "affectsGlobalScope": true
78 | },
79 | "../../node_modules/typescript/lib/lib.es2016.array.include.d.ts": {
80 | "version": "3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006",
81 | "signature": "3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006",
82 | "affectsGlobalScope": true
83 | },
84 | "../../node_modules/typescript/lib/lib.es2017.object.d.ts": {
85 | "version": "17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a",
86 | "signature": "17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a",
87 | "affectsGlobalScope": true
88 | },
89 | "../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts": {
90 | "version": "7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98",
91 | "signature": "7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98",
92 | "affectsGlobalScope": true
93 | },
94 | "../../node_modules/typescript/lib/lib.es2017.string.d.ts": {
95 | "version": "6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577",
96 | "signature": "6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577",
97 | "affectsGlobalScope": true
98 | },
99 | "../../node_modules/typescript/lib/lib.es2017.intl.d.ts": {
100 | "version": "12a310447c5d23c7d0d5ca2af606e3bd08afda69100166730ab92c62999ebb9d",
101 | "signature": "12a310447c5d23c7d0d5ca2af606e3bd08afda69100166730ab92c62999ebb9d",
102 | "affectsGlobalScope": true
103 | },
104 | "../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts": {
105 | "version": "b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e",
106 | "signature": "b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e",
107 | "affectsGlobalScope": true
108 | },
109 | "../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts": {
110 | "version": "0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a",
111 | "signature": "0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a",
112 | "affectsGlobalScope": true
113 | },
114 | "../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts": {
115 | "version": "a40c4d82bf13fcded295ac29f354eb7d40249613c15e07b53f2fc75e45e16359",
116 | "signature": "a40c4d82bf13fcded295ac29f354eb7d40249613c15e07b53f2fc75e45e16359",
117 | "affectsGlobalScope": true
118 | },
119 | "../../node_modules/typescript/lib/lib.es2018.intl.d.ts": {
120 | "version": "df9c8a72ca8b0ed62f5470b41208a0587f0f73f0a7db28e5a1272cf92537518e",
121 | "signature": "df9c8a72ca8b0ed62f5470b41208a0587f0f73f0a7db28e5a1272cf92537518e",
122 | "affectsGlobalScope": true
123 | },
124 | "../../node_modules/typescript/lib/lib.es2018.promise.d.ts": {
125 | "version": "bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c",
126 | "signature": "bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c",
127 | "affectsGlobalScope": true
128 | },
129 | "../../node_modules/typescript/lib/lib.es2018.regexp.d.ts": {
130 | "version": "c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8",
131 | "signature": "c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8",
132 | "affectsGlobalScope": true
133 | },
134 | "../../node_modules/typescript/lib/lib.es2020.bigint.d.ts": {
135 | "version": "7b5a10e3c897fabece5a51aa85b4111727d7adb53c2734b5d37230ff96802a09",
136 | "signature": "7b5a10e3c897fabece5a51aa85b4111727d7adb53c2734b5d37230ff96802a09",
137 | "affectsGlobalScope": true
138 | },
139 | "../../node_modules/typescript/lib/lib.esnext.intl.d.ts": {
140 | "version": "89bf2b7a601b73ea4311eda9c41f86a58994fec1bee3b87c4a14d68d9adcdcbd",
141 | "signature": "89bf2b7a601b73ea4311eda9c41f86a58994fec1bee3b87c4a14d68d9adcdcbd",
142 | "affectsGlobalScope": true
143 | },
144 | "./index.ts": {
145 | "version": "79f6a3aa3889c38247d7e8668c50fe6acb1acf7470c6c2ba973c1054277f0489",
146 | "signature": "c9e5f09ba6c9bcb7d8627cd56874cfbdc95a91f66f39dab5db02906ea5a94dfe",
147 | "affectsGlobalScope": true
148 | },
149 | "../../node_modules/@babel/types/lib/index.d.ts": {
150 | "version": "7c6b4c3bbc2c3cebe5cc1364e84a4fd0cbda5fda186c0ba15c2f693f403479d2",
151 | "signature": "7c6b4c3bbc2c3cebe5cc1364e84a4fd0cbda5fda186c0ba15c2f693f403479d2",
152 | "affectsGlobalScope": false
153 | },
154 | "../../node_modules/@types/babel__generator/index.d.ts": {
155 | "version": "b25c5f2970d06c729f464c0aeaa64b1a5b5f1355aa93554bb5f9c199b8624b1e",
156 | "signature": "b25c5f2970d06c729f464c0aeaa64b1a5b5f1355aa93554bb5f9c199b8624b1e",
157 | "affectsGlobalScope": false
158 | },
159 | "../../node_modules/@types/babel__traverse/index.d.ts": {
160 | "version": "8a278bfba7b081cd849434c1130655046639ae90617a682436ed6954e2b57403",
161 | "signature": "8a278bfba7b081cd849434c1130655046639ae90617a682436ed6954e2b57403",
162 | "affectsGlobalScope": false
163 | },
164 | "../../node_modules/@babel/parser/typings/babel-parser.d.ts": {
165 | "version": "6da9e714516d081abaa435946d77c8d74dba888530412dc71601e83d2c8a512e",
166 | "signature": "6da9e714516d081abaa435946d77c8d74dba888530412dc71601e83d2c8a512e",
167 | "affectsGlobalScope": false
168 | },
169 | "../../node_modules/@types/babel__template/index.d.ts": {
170 | "version": "3051751533eee92572241b3cef28333212401408c4e7aa21718714b793c0f4ed",
171 | "signature": "3051751533eee92572241b3cef28333212401408c4e7aa21718714b793c0f4ed",
172 | "affectsGlobalScope": false
173 | },
174 | "../../node_modules/@types/babel__core/index.d.ts": {
175 | "version": "a66e700ed470a0cb52d14f3376c1605c70fec8e9659e45f7e22ad07fcd06ae04",
176 | "signature": "a66e700ed470a0cb52d14f3376c1605c70fec8e9659e45f7e22ad07fcd06ae04",
177 | "affectsGlobalScope": false
178 | },
179 | "../../node_modules/@types/node/globals.d.ts": {
180 | "version": "215d8d9a2c480fd460127edc048d68d9931d3b27f95132253a6e71975f060bb1",
181 | "signature": "215d8d9a2c480fd460127edc048d68d9931d3b27f95132253a6e71975f060bb1",
182 | "affectsGlobalScope": true
183 | },
184 | "../../node_modules/@types/node/async_hooks.d.ts": {
185 | "version": "c438b413e94ff76dfa20ae005f33a1c84f2480d1d66e0fd687501020d0de9b50",
186 | "signature": "c438b413e94ff76dfa20ae005f33a1c84f2480d1d66e0fd687501020d0de9b50",
187 | "affectsGlobalScope": false
188 | },
189 | "../../node_modules/@types/node/buffer.d.ts": {
190 | "version": "bc6a78961535181265845bf9b9e8a147ffd0ca275097ceb670a9b92afa825152",
191 | "signature": "bc6a78961535181265845bf9b9e8a147ffd0ca275097ceb670a9b92afa825152",
192 | "affectsGlobalScope": false
193 | },
194 | "../../node_modules/@types/node/child_process.d.ts": {
195 | "version": "a4b5411d87995b9fb847f491f4388b38f829d8ab39be3e2fd65a3e40709f29a8",
196 | "signature": "a4b5411d87995b9fb847f491f4388b38f829d8ab39be3e2fd65a3e40709f29a8",
197 | "affectsGlobalScope": false
198 | },
199 | "../../node_modules/@types/node/cluster.d.ts": {
200 | "version": "123ec69e4b3a686eb49afd94ebe3292a5c84a867ecbcb6bb84bdd720a12af803",
201 | "signature": "123ec69e4b3a686eb49afd94ebe3292a5c84a867ecbcb6bb84bdd720a12af803",
202 | "affectsGlobalScope": false
203 | },
204 | "../../node_modules/@types/node/console.d.ts": {
205 | "version": "eb5197aade83cb0e360ac407289c53a8009e8fdae7939892a0240d30444496b6",
206 | "signature": "eb5197aade83cb0e360ac407289c53a8009e8fdae7939892a0240d30444496b6",
207 | "affectsGlobalScope": true
208 | },
209 | "../../node_modules/@types/node/constants.d.ts": {
210 | "version": "90c85ddbb8de82cd19198bda062065fc51b7407c0f206f2e399e65a52e979720",
211 | "signature": "90c85ddbb8de82cd19198bda062065fc51b7407c0f206f2e399e65a52e979720",
212 | "affectsGlobalScope": false
213 | },
214 | "../../node_modules/@types/node/crypto.d.ts": {
215 | "version": "3d9c3ccc05ebc6e288bef007bcc47a2fc0dce748ea634093ef0732b9be743805",
216 | "signature": "3d9c3ccc05ebc6e288bef007bcc47a2fc0dce748ea634093ef0732b9be743805",
217 | "affectsGlobalScope": false
218 | },
219 | "../../node_modules/@types/node/dgram.d.ts": {
220 | "version": "7e050b767ed10c7ffbc01f314defbf420bf0b5d54ce666e1c87507c035dfc191",
221 | "signature": "7e050b767ed10c7ffbc01f314defbf420bf0b5d54ce666e1c87507c035dfc191",
222 | "affectsGlobalScope": false
223 | },
224 | "../../node_modules/@types/node/dns.d.ts": {
225 | "version": "51f82a7e0819a91c170eb1ad39ad1917a0cbb8f9354fdaed66a5189745f63f71",
226 | "signature": "51f82a7e0819a91c170eb1ad39ad1917a0cbb8f9354fdaed66a5189745f63f71",
227 | "affectsGlobalScope": false
228 | },
229 | "../../node_modules/@types/node/domain.d.ts": {
230 | "version": "2866a528b2708aa272ec3eaafd3c980abb23aec1ef831cfc5eb2186b98c37ce5",
231 | "signature": "2866a528b2708aa272ec3eaafd3c980abb23aec1ef831cfc5eb2186b98c37ce5",
232 | "affectsGlobalScope": true
233 | },
234 | "../../node_modules/@types/node/events.d.ts": {
235 | "version": "153d835dc32985120790e10102834b0a5bd979bb5e42bfbb33c0ff6260cf03ce",
236 | "signature": "153d835dc32985120790e10102834b0a5bd979bb5e42bfbb33c0ff6260cf03ce",
237 | "affectsGlobalScope": true
238 | },
239 | "../../node_modules/@types/node/fs.d.ts": {
240 | "version": "2e204fb437b8e98937c933cb7e739b24b871872161997d7dfe98841b861a14f0",
241 | "signature": "2e204fb437b8e98937c933cb7e739b24b871872161997d7dfe98841b861a14f0",
242 | "affectsGlobalScope": false
243 | },
244 | "../../node_modules/@types/node/fs/promises.d.ts": {
245 | "version": "1c0692002778565d9b3ee0edea6ca133caadd714597228525fec8e2fd9846755",
246 | "signature": "1c0692002778565d9b3ee0edea6ca133caadd714597228525fec8e2fd9846755",
247 | "affectsGlobalScope": false
248 | },
249 | "../../node_modules/@types/node/http.d.ts": {
250 | "version": "f2f8a385694fd71a421616cbaca477a539f30f4098f11261b1d188d72dc3478a",
251 | "signature": "f2f8a385694fd71a421616cbaca477a539f30f4098f11261b1d188d72dc3478a",
252 | "affectsGlobalScope": false
253 | },
254 | "../../node_modules/@types/node/http2.d.ts": {
255 | "version": "f15f1f1104aaf47d25124de81949375416e3f8ee704e3d221bea339e35421edb",
256 | "signature": "f15f1f1104aaf47d25124de81949375416e3f8ee704e3d221bea339e35421edb",
257 | "affectsGlobalScope": false
258 | },
259 | "../../node_modules/@types/node/https.d.ts": {
260 | "version": "c969bf4c7cdfe4d5dd28aa09432f99d09ad1d8d8b839959646579521d0467d1a",
261 | "signature": "c969bf4c7cdfe4d5dd28aa09432f99d09ad1d8d8b839959646579521d0467d1a",
262 | "affectsGlobalScope": false
263 | },
264 | "../../node_modules/@types/node/inspector.d.ts": {
265 | "version": "6c3857edaeeaaf43812f527830ebeece9266b6e8eb5271ab6d2f0008306c9947",
266 | "signature": "6c3857edaeeaaf43812f527830ebeece9266b6e8eb5271ab6d2f0008306c9947",
267 | "affectsGlobalScope": false
268 | },
269 | "../../node_modules/@types/node/module.d.ts": {
270 | "version": "bc6a77e750f4d34584e46b1405b771fb69a224197dd6bafe5b0392a29a70b665",
271 | "signature": "bc6a77e750f4d34584e46b1405b771fb69a224197dd6bafe5b0392a29a70b665",
272 | "affectsGlobalScope": false
273 | },
274 | "../../node_modules/@types/node/net.d.ts": {
275 | "version": "3c5edfced8c5cd35e3680789deabbe4f478b67a42b26d82d91eea9d3f07f4771",
276 | "signature": "3c5edfced8c5cd35e3680789deabbe4f478b67a42b26d82d91eea9d3f07f4771",
277 | "affectsGlobalScope": false
278 | },
279 | "../../node_modules/@types/node/os.d.ts": {
280 | "version": "ed4ae81196cccc10f297d228bca8d02e31058e6d723a3c5bc4be5fb3c61c6a34",
281 | "signature": "ed4ae81196cccc10f297d228bca8d02e31058e6d723a3c5bc4be5fb3c61c6a34",
282 | "affectsGlobalScope": false
283 | },
284 | "../../node_modules/@types/node/path.d.ts": {
285 | "version": "84044697c8b3e08ef24e4b32cfe6440143d07e469a5e34bda0635276d32d9f35",
286 | "signature": "84044697c8b3e08ef24e4b32cfe6440143d07e469a5e34bda0635276d32d9f35",
287 | "affectsGlobalScope": false
288 | },
289 | "../../node_modules/@types/node/perf_hooks.d.ts": {
290 | "version": "4982d94cb6427263c8839d8d6324a8bbe129e931deb61a7380f8fad17ba2cfc0",
291 | "signature": "4982d94cb6427263c8839d8d6324a8bbe129e931deb61a7380f8fad17ba2cfc0",
292 | "affectsGlobalScope": false
293 | },
294 | "../../node_modules/@types/node/process.d.ts": {
295 | "version": "ae4bc1dd4d9de7bbea6ce419db45af82a81358e6014c9e1235b5d252e06f8ab8",
296 | "signature": "ae4bc1dd4d9de7bbea6ce419db45af82a81358e6014c9e1235b5d252e06f8ab8",
297 | "affectsGlobalScope": true
298 | },
299 | "../../node_modules/@types/node/punycode.d.ts": {
300 | "version": "3f6a1fd73c9dc3bd7f4b79bc075297ca6527904df69b0f2c2c94e4c4c7d9a32c",
301 | "signature": "3f6a1fd73c9dc3bd7f4b79bc075297ca6527904df69b0f2c2c94e4c4c7d9a32c",
302 | "affectsGlobalScope": false
303 | },
304 | "../../node_modules/@types/node/querystring.d.ts": {
305 | "version": "884560fda6c3868f925f022adc3a1289fe6507bbb45adb10fa1bbcc73a941bb0",
306 | "signature": "884560fda6c3868f925f022adc3a1289fe6507bbb45adb10fa1bbcc73a941bb0",
307 | "affectsGlobalScope": false
308 | },
309 | "../../node_modules/@types/node/readline.d.ts": {
310 | "version": "6b2bb67b0942bcfce93e1d6fad5f70afd54940a2b13df7f311201fba54b2cbe9",
311 | "signature": "6b2bb67b0942bcfce93e1d6fad5f70afd54940a2b13df7f311201fba54b2cbe9",
312 | "affectsGlobalScope": false
313 | },
314 | "../../node_modules/@types/node/repl.d.ts": {
315 | "version": "acbed967a379b3e9f73237ba9473f8b337eeea14b7dc64d445430b5d695751da",
316 | "signature": "acbed967a379b3e9f73237ba9473f8b337eeea14b7dc64d445430b5d695751da",
317 | "affectsGlobalScope": false
318 | },
319 | "../../node_modules/@types/node/stream.d.ts": {
320 | "version": "e7b5a3f40f19d9eea71890c70dfb37ac5dd82cbffe5f95bc8f23c536455732d0",
321 | "signature": "e7b5a3f40f19d9eea71890c70dfb37ac5dd82cbffe5f95bc8f23c536455732d0",
322 | "affectsGlobalScope": false
323 | },
324 | "../../node_modules/@types/node/string_decoder.d.ts": {
325 | "version": "d67e08745494b000da9410c1ae2fdc9965fc6d593fe0f381a47491f75417d457",
326 | "signature": "d67e08745494b000da9410c1ae2fdc9965fc6d593fe0f381a47491f75417d457",
327 | "affectsGlobalScope": false
328 | },
329 | "../../node_modules/@types/node/timers.d.ts": {
330 | "version": "b40652bf8ce4a18133b31349086523b219724dca8df3448c1a0742528e7ad5b9",
331 | "signature": "b40652bf8ce4a18133b31349086523b219724dca8df3448c1a0742528e7ad5b9",
332 | "affectsGlobalScope": false
333 | },
334 | "../../node_modules/@types/node/tls.d.ts": {
335 | "version": "01c351e71743ff26450789ec4ca6a1421c647c9c459aa8007e9e1914073b5db2",
336 | "signature": "01c351e71743ff26450789ec4ca6a1421c647c9c459aa8007e9e1914073b5db2",
337 | "affectsGlobalScope": false
338 | },
339 | "../../node_modules/@types/node/trace_events.d.ts": {
340 | "version": "a77fdb357c78b70142b2fdbbfb72958d69e8f765fd2a3c69946c1018e89d4638",
341 | "signature": "a77fdb357c78b70142b2fdbbfb72958d69e8f765fd2a3c69946c1018e89d4638",
342 | "affectsGlobalScope": false
343 | },
344 | "../../node_modules/@types/node/tty.d.ts": {
345 | "version": "3c2ac350c3baa61fd2b1925844109e098f4376d0768a4643abc82754fd752748",
346 | "signature": "3c2ac350c3baa61fd2b1925844109e098f4376d0768a4643abc82754fd752748",
347 | "affectsGlobalScope": false
348 | },
349 | "../../node_modules/@types/node/url.d.ts": {
350 | "version": "4001971b90f18161f7bd46d68150d32a5da47e3f177956a267a2b29a2771896a",
351 | "signature": "4001971b90f18161f7bd46d68150d32a5da47e3f177956a267a2b29a2771896a",
352 | "affectsGlobalScope": false
353 | },
354 | "../../node_modules/@types/node/util.d.ts": {
355 | "version": "f28704c27e1bd58068052f5407541a3306f0ffc77f068e2891f46527a4569e25",
356 | "signature": "f28704c27e1bd58068052f5407541a3306f0ffc77f068e2891f46527a4569e25",
357 | "affectsGlobalScope": false
358 | },
359 | "../../node_modules/@types/node/v8.d.ts": {
360 | "version": "289be113bad7ee27ee7fa5b1e373c964c9789a5e9ed7db5ddcb631371120b953",
361 | "signature": "289be113bad7ee27ee7fa5b1e373c964c9789a5e9ed7db5ddcb631371120b953",
362 | "affectsGlobalScope": false
363 | },
364 | "../../node_modules/@types/node/vm.d.ts": {
365 | "version": "baf0b82ffc5d2616f44a6fb1f81e8d798545bebf0c30f5d8b003a1dba1acfb3f",
366 | "signature": "baf0b82ffc5d2616f44a6fb1f81e8d798545bebf0c30f5d8b003a1dba1acfb3f",
367 | "affectsGlobalScope": false
368 | },
369 | "../../node_modules/@types/node/worker_threads.d.ts": {
370 | "version": "c6a5b34f1e725019445754f1e733585f113e0dced75f137bd3c4af5853d3f6ab",
371 | "signature": "c6a5b34f1e725019445754f1e733585f113e0dced75f137bd3c4af5853d3f6ab",
372 | "affectsGlobalScope": false
373 | },
374 | "../../node_modules/@types/node/zlib.d.ts": {
375 | "version": "15fbe50526244954eb2f933546bca6cdcf0db16c9428d099b3b386c1db5799ab",
376 | "signature": "15fbe50526244954eb2f933546bca6cdcf0db16c9428d099b3b386c1db5799ab",
377 | "affectsGlobalScope": false
378 | },
379 | "../../node_modules/@types/node/ts3.4/base.d.ts": {
380 | "version": "d44028ae0127eb3e9fcfa5f55a8b81d64775ce15aca1020fe25c511bbb055834",
381 | "signature": "d44028ae0127eb3e9fcfa5f55a8b81d64775ce15aca1020fe25c511bbb055834",
382 | "affectsGlobalScope": false
383 | },
384 | "../../node_modules/@types/node/globals.global.d.ts": {
385 | "version": "2708349d5a11a5c2e5f3a0765259ebe7ee00cdcc8161cb9990cb4910328442a1",
386 | "signature": "2708349d5a11a5c2e5f3a0765259ebe7ee00cdcc8161cb9990cb4910328442a1",
387 | "affectsGlobalScope": true
388 | },
389 | "../../node_modules/@types/node/wasi.d.ts": {
390 | "version": "4e0a4d84b15692ea8669fe4f3d05a4f204567906b1347da7a58b75f45bae48d3",
391 | "signature": "4e0a4d84b15692ea8669fe4f3d05a4f204567906b1347da7a58b75f45bae48d3",
392 | "affectsGlobalScope": false
393 | },
394 | "../../node_modules/@types/node/ts3.6/base.d.ts": {
395 | "version": "ad1ae5ae98eceb9af99061e83e867b9897d267aebc8f3b938c9424deabadf4bb",
396 | "signature": "ad1ae5ae98eceb9af99061e83e867b9897d267aebc8f3b938c9424deabadf4bb",
397 | "affectsGlobalScope": false
398 | },
399 | "../../node_modules/@types/node/assert.d.ts": {
400 | "version": "b3593bd345ebea5e4d0a894c03251a3774b34df3d6db57075c18e089a599ba76",
401 | "signature": "b3593bd345ebea5e4d0a894c03251a3774b34df3d6db57075c18e089a599ba76",
402 | "affectsGlobalScope": false
403 | },
404 | "../../node_modules/@types/node/base.d.ts": {
405 | "version": "e61a21e9418f279bc480394a94d1581b2dee73747adcbdef999b6737e34d721b",
406 | "signature": "e61a21e9418f279bc480394a94d1581b2dee73747adcbdef999b6737e34d721b",
407 | "affectsGlobalScope": false
408 | },
409 | "../../node_modules/@types/node/index.d.ts": {
410 | "version": "744e6430bafc6f39f66c4fc1e6a0d8c9551260ffd1782aa7e3f5166ac6aa1f86",
411 | "signature": "744e6430bafc6f39f66c4fc1e6a0d8c9551260ffd1782aa7e3f5166ac6aa1f86",
412 | "affectsGlobalScope": false
413 | },
414 | "../../node_modules/@types/graceful-fs/index.d.ts": {
415 | "version": "3ebae8c00411116a66fca65b08228ea0cf0b72724701f9b854442100aab55aba",
416 | "signature": "3ebae8c00411116a66fca65b08228ea0cf0b72724701f9b854442100aab55aba",
417 | "affectsGlobalScope": false
418 | },
419 | "../../node_modules/@types/istanbul-lib-coverage/index.d.ts": {
420 | "version": "de18acda71730bac52f4b256ce7511bb56cc21f6f114c59c46782eff2f632857",
421 | "signature": "de18acda71730bac52f4b256ce7511bb56cc21f6f114c59c46782eff2f632857",
422 | "affectsGlobalScope": false
423 | },
424 | "../../node_modules/@types/istanbul-lib-report/index.d.ts": {
425 | "version": "7eb06594824ada538b1d8b48c3925a83e7db792f47a081a62cf3e5c4e23cf0ee",
426 | "signature": "7eb06594824ada538b1d8b48c3925a83e7db792f47a081a62cf3e5c4e23cf0ee",
427 | "affectsGlobalScope": false
428 | },
429 | "../../node_modules/@types/istanbul-reports/index.d.ts": {
430 | "version": "905c3e8f7ddaa6c391b60c05b2f4c3931d7127ad717a080359db3df510b7bdab",
431 | "signature": "905c3e8f7ddaa6c391b60c05b2f4c3931d7127ad717a080359db3df510b7bdab",
432 | "affectsGlobalScope": false
433 | },
434 | "../../node_modules/jest-diff/build/cleanupsemantic.d.ts": {
435 | "version": "d8aab31ba8e618cc3eea10b0945de81cb93b7e8150a013a482332263b9305322",
436 | "signature": "d8aab31ba8e618cc3eea10b0945de81cb93b7e8150a013a482332263b9305322",
437 | "affectsGlobalScope": false
438 | },
439 | "../../node_modules/jest-diff/build/types.d.ts": {
440 | "version": "69da61a7b5093dac77fa3bec8be95dcf9a74c95a0e9161edb98bb24e30e439d2",
441 | "signature": "69da61a7b5093dac77fa3bec8be95dcf9a74c95a0e9161edb98bb24e30e439d2",
442 | "affectsGlobalScope": false
443 | },
444 | "../../node_modules/jest-diff/build/difflines.d.ts": {
445 | "version": "561eca7a381b96d6ccac6e4061e6d2ae53f5bc44203f3fd9f5b26864c32ae6e9",
446 | "signature": "561eca7a381b96d6ccac6e4061e6d2ae53f5bc44203f3fd9f5b26864c32ae6e9",
447 | "affectsGlobalScope": false
448 | },
449 | "../../node_modules/jest-diff/build/printdiffs.d.ts": {
450 | "version": "62ea38627e3ebab429f7616812a9394d327c2bc271003dfba985de9b4137369f",
451 | "signature": "62ea38627e3ebab429f7616812a9394d327c2bc271003dfba985de9b4137369f",
452 | "affectsGlobalScope": false
453 | },
454 | "../../node_modules/jest-diff/build/index.d.ts": {
455 | "version": "b4439890c168d646357928431100daac5cbdee1d345a34e6bf6eca9f3abe22bc",
456 | "signature": "b4439890c168d646357928431100daac5cbdee1d345a34e6bf6eca9f3abe22bc",
457 | "affectsGlobalScope": false
458 | },
459 | "../../node_modules/pretty-format/build/types.d.ts": {
460 | "version": "5d72971a459517c44c1379dab9ed248e87a61ba0a1e0f25c9d67e1e640cd9a09",
461 | "signature": "5d72971a459517c44c1379dab9ed248e87a61ba0a1e0f25c9d67e1e640cd9a09",
462 | "affectsGlobalScope": false
463 | },
464 | "../../node_modules/pretty-format/build/index.d.ts": {
465 | "version": "02d734976af36f4273d930bea88b3e62adf6b078cf120c1c63d49aa8d8427c5c",
466 | "signature": "02d734976af36f4273d930bea88b3e62adf6b078cf120c1c63d49aa8d8427c5c",
467 | "affectsGlobalScope": false
468 | },
469 | "../../node_modules/@types/jest/index.d.ts": {
470 | "version": "71f30fba971582dc744373cbc8b06c1eb64dc24a6ccbc9b457f94fb68c67cb4e",
471 | "signature": "71f30fba971582dc744373cbc8b06c1eb64dc24a6ccbc9b457f94fb68c67cb4e",
472 | "affectsGlobalScope": true
473 | },
474 | "../../node_modules/@types/normalize-package-data/index.d.ts": {
475 | "version": "c9ad058b2cc9ce6dc2ed92960d6d009e8c04bef46d3f5312283debca6869f613",
476 | "signature": "c9ad058b2cc9ce6dc2ed92960d6d009e8c04bef46d3f5312283debca6869f613",
477 | "affectsGlobalScope": false
478 | },
479 | "../../node_modules/@types/prettier/index.d.ts": {
480 | "version": "d916cd19ddfd778aaa1dbfad1adbc5cddf5172b42cbc85964084556ea5eaace5",
481 | "signature": "d916cd19ddfd778aaa1dbfad1adbc5cddf5172b42cbc85964084556ea5eaace5",
482 | "affectsGlobalScope": false
483 | },
484 | "../../node_modules/@types/stack-utils/index.d.ts": {
485 | "version": "c6c4fea9acc55d5e38ff2b70d57ab0b5cdbd08f8bc5d7a226e322cea128c5b57",
486 | "signature": "c6c4fea9acc55d5e38ff2b70d57ab0b5cdbd08f8bc5d7a226e322cea128c5b57",
487 | "affectsGlobalScope": false
488 | },
489 | "../../node_modules/@types/yargs-parser/index.d.ts": {
490 | "version": "3bdd93ec24853e61bfa4c63ebaa425ff3e474156e87a47d90122e1d8cc717c1f",
491 | "signature": "3bdd93ec24853e61bfa4c63ebaa425ff3e474156e87a47d90122e1d8cc717c1f",
492 | "affectsGlobalScope": false
493 | },
494 | "../../node_modules/@types/yargs/index.d.ts": {
495 | "version": "5a2a25feca554a8f289ed62114771b8c63d89f2b58325e2f8b7043e4e0160d11",
496 | "signature": "5a2a25feca554a8f289ed62114771b8c63d89f2b58325e2f8b7043e4e0160d11",
497 | "affectsGlobalScope": false
498 | }
499 | },
500 | "options": {
501 | "target": 1,
502 | "module": 1,
503 | "lib": [
504 | "lib.dom.d.ts"
505 | ],
506 | "sourceMap": true,
507 | "outDir": "./",
508 | "downlevelIteration": true,
509 | "strict": true,
510 | "noImplicitAny": false,
511 | "strictNullChecks": true,
512 | "esModuleInterop": true,
513 | "experimentalDecorators": true,
514 | "emitDecoratorMetadata": true,
515 | "skipLibCheck": true,
516 | "forceConsistentCasingInFileNames": true,
517 | "composite": true,
518 | "project": "./tsconfig.json",
519 | "configFilePath": "./tsconfig.json"
520 | },
521 | "referencedMap": {
522 | "../../node_modules/@babel/parser/typings/babel-parser.d.ts": [
523 | "../../node_modules/@babel/types/lib/index.d.ts"
524 | ],
525 | "../../node_modules/@types/babel__core/index.d.ts": [
526 | "../../node_modules/@babel/parser/typings/babel-parser.d.ts",
527 | "../../node_modules/@babel/types/lib/index.d.ts",
528 | "../../node_modules/@types/babel__generator/index.d.ts",
529 | "../../node_modules/@types/babel__template/index.d.ts",
530 | "../../node_modules/@types/babel__traverse/index.d.ts"
531 | ],
532 | "../../node_modules/@types/babel__generator/index.d.ts": [
533 | "../../node_modules/@babel/types/lib/index.d.ts"
534 | ],
535 | "../../node_modules/@types/babel__template/index.d.ts": [
536 | "../../node_modules/@babel/parser/typings/babel-parser.d.ts",
537 | "../../node_modules/@babel/types/lib/index.d.ts"
538 | ],
539 | "../../node_modules/@types/babel__traverse/index.d.ts": [
540 | "../../node_modules/@babel/types/lib/index.d.ts"
541 | ],
542 | "../../node_modules/@types/graceful-fs/index.d.ts": [
543 | "../../node_modules/@types/node/fs.d.ts",
544 | "../../node_modules/@types/node/index.d.ts"
545 | ],
546 | "../../node_modules/@types/istanbul-lib-report/index.d.ts": [
547 | "../../node_modules/@types/istanbul-lib-coverage/index.d.ts"
548 | ],
549 | "../../node_modules/@types/istanbul-reports/index.d.ts": [
550 | "../../node_modules/@types/istanbul-lib-report/index.d.ts"
551 | ],
552 | "../../node_modules/@types/jest/index.d.ts": [
553 | "../../node_modules/jest-diff/build/index.d.ts",
554 | "../../node_modules/pretty-format/build/index.d.ts"
555 | ],
556 | "../../node_modules/@types/node/base.d.ts": [
557 | "../../node_modules/@types/node/assert.d.ts",
558 | "../../node_modules/@types/node/ts3.6/base.d.ts"
559 | ],
560 | "../../node_modules/@types/node/child_process.d.ts": [
561 | "../../node_modules/@types/node/events.d.ts",
562 | "../../node_modules/@types/node/fs.d.ts",
563 | "../../node_modules/@types/node/net.d.ts",
564 | "../../node_modules/@types/node/stream.d.ts"
565 | ],
566 | "../../node_modules/@types/node/cluster.d.ts": [
567 | "../../node_modules/@types/node/child_process.d.ts",
568 | "../../node_modules/@types/node/events.d.ts",
569 | "../../node_modules/@types/node/net.d.ts"
570 | ],
571 | "../../node_modules/@types/node/console.d.ts": [
572 | "../../node_modules/@types/node/util.d.ts"
573 | ],
574 | "../../node_modules/@types/node/constants.d.ts": [
575 | "../../node_modules/@types/node/crypto.d.ts",
576 | "../../node_modules/@types/node/fs.d.ts",
577 | "../../node_modules/@types/node/os.d.ts"
578 | ],
579 | "../../node_modules/@types/node/crypto.d.ts": [
580 | "../../node_modules/@types/node/stream.d.ts"
581 | ],
582 | "../../node_modules/@types/node/dgram.d.ts": [
583 | "../../node_modules/@types/node/dns.d.ts",
584 | "../../node_modules/@types/node/events.d.ts",
585 | "../../node_modules/@types/node/net.d.ts"
586 | ],
587 | "../../node_modules/@types/node/domain.d.ts": [
588 | "../../node_modules/@types/node/events.d.ts"
589 | ],
590 | "../../node_modules/@types/node/events.d.ts": [
591 | "../../node_modules/@types/node/events.d.ts"
592 | ],
593 | "../../node_modules/@types/node/fs.d.ts": [
594 | "../../node_modules/@types/node/events.d.ts",
595 | "../../node_modules/@types/node/fs/promises.d.ts",
596 | "../../node_modules/@types/node/stream.d.ts",
597 | "../../node_modules/@types/node/url.d.ts"
598 | ],
599 | "../../node_modules/@types/node/fs/promises.d.ts": [
600 | "../../node_modules/@types/node/fs.d.ts"
601 | ],
602 | "../../node_modules/@types/node/http.d.ts": [
603 | "../../node_modules/@types/node/net.d.ts",
604 | "../../node_modules/@types/node/stream.d.ts",
605 | "../../node_modules/@types/node/url.d.ts"
606 | ],
607 | "../../node_modules/@types/node/http2.d.ts": [
608 | "../../node_modules/@types/node/events.d.ts",
609 | "../../node_modules/@types/node/fs.d.ts",
610 | "../../node_modules/@types/node/http.d.ts",
611 | "../../node_modules/@types/node/net.d.ts",
612 | "../../node_modules/@types/node/stream.d.ts",
613 | "../../node_modules/@types/node/tls.d.ts",
614 | "../../node_modules/@types/node/url.d.ts"
615 | ],
616 | "../../node_modules/@types/node/https.d.ts": [
617 | "../../node_modules/@types/node/events.d.ts",
618 | "../../node_modules/@types/node/http.d.ts",
619 | "../../node_modules/@types/node/tls.d.ts",
620 | "../../node_modules/@types/node/url.d.ts"
621 | ],
622 | "../../node_modules/@types/node/index.d.ts": [
623 | "../../node_modules/@types/node/base.d.ts"
624 | ],
625 | "../../node_modules/@types/node/inspector.d.ts": [
626 | "../../node_modules/@types/node/events.d.ts"
627 | ],
628 | "../../node_modules/@types/node/module.d.ts": [
629 | "../../node_modules/@types/node/url.d.ts"
630 | ],
631 | "../../node_modules/@types/node/net.d.ts": [
632 | "../../node_modules/@types/node/dns.d.ts",
633 | "../../node_modules/@types/node/events.d.ts",
634 | "../../node_modules/@types/node/stream.d.ts"
635 | ],
636 | "../../node_modules/@types/node/perf_hooks.d.ts": [
637 | "../../node_modules/@types/node/async_hooks.d.ts"
638 | ],
639 | "../../node_modules/@types/node/process.d.ts": [
640 | "../../node_modules/@types/node/tty.d.ts"
641 | ],
642 | "../../node_modules/@types/node/readline.d.ts": [
643 | "../../node_modules/@types/node/events.d.ts",
644 | "../../node_modules/@types/node/stream.d.ts"
645 | ],
646 | "../../node_modules/@types/node/repl.d.ts": [
647 | "../../node_modules/@types/node/readline.d.ts",
648 | "../../node_modules/@types/node/util.d.ts",
649 | "../../node_modules/@types/node/vm.d.ts"
650 | ],
651 | "../../node_modules/@types/node/stream.d.ts": [
652 | "../../node_modules/@types/node/events.d.ts"
653 | ],
654 | "../../node_modules/@types/node/tls.d.ts": [
655 | "../../node_modules/@types/node/crypto.d.ts",
656 | "../../node_modules/@types/node/dns.d.ts",
657 | "../../node_modules/@types/node/net.d.ts",
658 | "../../node_modules/@types/node/stream.d.ts"
659 | ],
660 | "../../node_modules/@types/node/ts3.4/base.d.ts": [
661 | "../../node_modules/@types/node/async_hooks.d.ts",
662 | "../../node_modules/@types/node/buffer.d.ts",
663 | "../../node_modules/@types/node/child_process.d.ts",
664 | "../../node_modules/@types/node/cluster.d.ts",
665 | "../../node_modules/@types/node/console.d.ts",
666 | "../../node_modules/@types/node/constants.d.ts",
667 | "../../node_modules/@types/node/crypto.d.ts",
668 | "../../node_modules/@types/node/dgram.d.ts",
669 | "../../node_modules/@types/node/dns.d.ts",
670 | "../../node_modules/@types/node/domain.d.ts",
671 | "../../node_modules/@types/node/events.d.ts",
672 | "../../node_modules/@types/node/fs.d.ts",
673 | "../../node_modules/@types/node/fs/promises.d.ts",
674 | "../../node_modules/@types/node/globals.d.ts",
675 | "../../node_modules/@types/node/http.d.ts",
676 | "../../node_modules/@types/node/http2.d.ts",
677 | "../../node_modules/@types/node/https.d.ts",
678 | "../../node_modules/@types/node/inspector.d.ts",
679 | "../../node_modules/@types/node/module.d.ts",
680 | "../../node_modules/@types/node/net.d.ts",
681 | "../../node_modules/@types/node/os.d.ts",
682 | "../../node_modules/@types/node/path.d.ts",
683 | "../../node_modules/@types/node/perf_hooks.d.ts",
684 | "../../node_modules/@types/node/process.d.ts",
685 | "../../node_modules/@types/node/punycode.d.ts",
686 | "../../node_modules/@types/node/querystring.d.ts",
687 | "../../node_modules/@types/node/readline.d.ts",
688 | "../../node_modules/@types/node/repl.d.ts",
689 | "../../node_modules/@types/node/stream.d.ts",
690 | "../../node_modules/@types/node/string_decoder.d.ts",
691 | "../../node_modules/@types/node/timers.d.ts",
692 | "../../node_modules/@types/node/tls.d.ts",
693 | "../../node_modules/@types/node/trace_events.d.ts",
694 | "../../node_modules/@types/node/tty.d.ts",
695 | "../../node_modules/@types/node/url.d.ts",
696 | "../../node_modules/@types/node/util.d.ts",
697 | "../../node_modules/@types/node/v8.d.ts",
698 | "../../node_modules/@types/node/vm.d.ts",
699 | "../../node_modules/@types/node/worker_threads.d.ts",
700 | "../../node_modules/@types/node/zlib.d.ts"
701 | ],
702 | "../../node_modules/@types/node/ts3.6/base.d.ts": [
703 | "../../node_modules/@types/node/globals.global.d.ts",
704 | "../../node_modules/@types/node/ts3.4/base.d.ts",
705 | "../../node_modules/@types/node/wasi.d.ts"
706 | ],
707 | "../../node_modules/@types/node/tty.d.ts": [
708 | "../../node_modules/@types/node/net.d.ts"
709 | ],
710 | "../../node_modules/@types/node/url.d.ts": [
711 | "../../node_modules/@types/node/querystring.d.ts"
712 | ],
713 | "../../node_modules/@types/node/v8.d.ts": [
714 | "../../node_modules/@types/node/stream.d.ts"
715 | ],
716 | "../../node_modules/@types/node/worker_threads.d.ts": [
717 | "../../node_modules/@types/node/events.d.ts",
718 | "../../node_modules/@types/node/fs/promises.d.ts",
719 | "../../node_modules/@types/node/stream.d.ts",
720 | "../../node_modules/@types/node/url.d.ts",
721 | "../../node_modules/@types/node/vm.d.ts"
722 | ],
723 | "../../node_modules/@types/node/zlib.d.ts": [
724 | "../../node_modules/@types/node/stream.d.ts"
725 | ],
726 | "../../node_modules/@types/yargs/index.d.ts": [
727 | "../../node_modules/@types/yargs-parser/index.d.ts"
728 | ],
729 | "../../node_modules/jest-diff/build/difflines.d.ts": [
730 | "../../node_modules/jest-diff/build/cleanupsemantic.d.ts",
731 | "../../node_modules/jest-diff/build/types.d.ts"
732 | ],
733 | "../../node_modules/jest-diff/build/index.d.ts": [
734 | "../../node_modules/jest-diff/build/cleanupsemantic.d.ts",
735 | "../../node_modules/jest-diff/build/difflines.d.ts",
736 | "../../node_modules/jest-diff/build/printdiffs.d.ts",
737 | "../../node_modules/jest-diff/build/types.d.ts"
738 | ],
739 | "../../node_modules/jest-diff/build/printdiffs.d.ts": [
740 | "../../node_modules/jest-diff/build/cleanupsemantic.d.ts",
741 | "../../node_modules/jest-diff/build/types.d.ts"
742 | ],
743 | "../../node_modules/pretty-format/build/index.d.ts": [
744 | "../../node_modules/pretty-format/build/types.d.ts"
745 | ]
746 | },
747 | "exportedModulesMap": {
748 | "../../node_modules/@babel/parser/typings/babel-parser.d.ts": [
749 | "../../node_modules/@babel/types/lib/index.d.ts"
750 | ],
751 | "../../node_modules/@types/babel__core/index.d.ts": [
752 | "../../node_modules/@babel/parser/typings/babel-parser.d.ts",
753 | "../../node_modules/@babel/types/lib/index.d.ts",
754 | "../../node_modules/@types/babel__generator/index.d.ts",
755 | "../../node_modules/@types/babel__template/index.d.ts",
756 | "../../node_modules/@types/babel__traverse/index.d.ts"
757 | ],
758 | "../../node_modules/@types/babel__generator/index.d.ts": [
759 | "../../node_modules/@babel/types/lib/index.d.ts"
760 | ],
761 | "../../node_modules/@types/babel__template/index.d.ts": [
762 | "../../node_modules/@babel/parser/typings/babel-parser.d.ts",
763 | "../../node_modules/@babel/types/lib/index.d.ts"
764 | ],
765 | "../../node_modules/@types/babel__traverse/index.d.ts": [
766 | "../../node_modules/@babel/types/lib/index.d.ts"
767 | ],
768 | "../../node_modules/@types/graceful-fs/index.d.ts": [
769 | "../../node_modules/@types/node/fs.d.ts",
770 | "../../node_modules/@types/node/index.d.ts"
771 | ],
772 | "../../node_modules/@types/istanbul-lib-report/index.d.ts": [
773 | "../../node_modules/@types/istanbul-lib-coverage/index.d.ts"
774 | ],
775 | "../../node_modules/@types/istanbul-reports/index.d.ts": [
776 | "../../node_modules/@types/istanbul-lib-report/index.d.ts"
777 | ],
778 | "../../node_modules/@types/jest/index.d.ts": [
779 | "../../node_modules/jest-diff/build/index.d.ts",
780 | "../../node_modules/pretty-format/build/index.d.ts"
781 | ],
782 | "../../node_modules/@types/node/base.d.ts": [
783 | "../../node_modules/@types/node/assert.d.ts",
784 | "../../node_modules/@types/node/ts3.6/base.d.ts"
785 | ],
786 | "../../node_modules/@types/node/child_process.d.ts": [
787 | "../../node_modules/@types/node/events.d.ts",
788 | "../../node_modules/@types/node/fs.d.ts",
789 | "../../node_modules/@types/node/net.d.ts",
790 | "../../node_modules/@types/node/stream.d.ts"
791 | ],
792 | "../../node_modules/@types/node/cluster.d.ts": [
793 | "../../node_modules/@types/node/child_process.d.ts",
794 | "../../node_modules/@types/node/events.d.ts",
795 | "../../node_modules/@types/node/net.d.ts"
796 | ],
797 | "../../node_modules/@types/node/console.d.ts": [
798 | "../../node_modules/@types/node/util.d.ts"
799 | ],
800 | "../../node_modules/@types/node/constants.d.ts": [
801 | "../../node_modules/@types/node/crypto.d.ts",
802 | "../../node_modules/@types/node/fs.d.ts",
803 | "../../node_modules/@types/node/os.d.ts"
804 | ],
805 | "../../node_modules/@types/node/crypto.d.ts": [
806 | "../../node_modules/@types/node/stream.d.ts"
807 | ],
808 | "../../node_modules/@types/node/dgram.d.ts": [
809 | "../../node_modules/@types/node/dns.d.ts",
810 | "../../node_modules/@types/node/events.d.ts",
811 | "../../node_modules/@types/node/net.d.ts"
812 | ],
813 | "../../node_modules/@types/node/domain.d.ts": [
814 | "../../node_modules/@types/node/events.d.ts"
815 | ],
816 | "../../node_modules/@types/node/events.d.ts": [
817 | "../../node_modules/@types/node/events.d.ts"
818 | ],
819 | "../../node_modules/@types/node/fs.d.ts": [
820 | "../../node_modules/@types/node/events.d.ts",
821 | "../../node_modules/@types/node/fs/promises.d.ts",
822 | "../../node_modules/@types/node/stream.d.ts",
823 | "../../node_modules/@types/node/url.d.ts"
824 | ],
825 | "../../node_modules/@types/node/fs/promises.d.ts": [
826 | "../../node_modules/@types/node/fs.d.ts"
827 | ],
828 | "../../node_modules/@types/node/http.d.ts": [
829 | "../../node_modules/@types/node/net.d.ts",
830 | "../../node_modules/@types/node/stream.d.ts",
831 | "../../node_modules/@types/node/url.d.ts"
832 | ],
833 | "../../node_modules/@types/node/http2.d.ts": [
834 | "../../node_modules/@types/node/events.d.ts",
835 | "../../node_modules/@types/node/fs.d.ts",
836 | "../../node_modules/@types/node/http.d.ts",
837 | "../../node_modules/@types/node/net.d.ts",
838 | "../../node_modules/@types/node/stream.d.ts",
839 | "../../node_modules/@types/node/tls.d.ts",
840 | "../../node_modules/@types/node/url.d.ts"
841 | ],
842 | "../../node_modules/@types/node/https.d.ts": [
843 | "../../node_modules/@types/node/events.d.ts",
844 | "../../node_modules/@types/node/http.d.ts",
845 | "../../node_modules/@types/node/tls.d.ts",
846 | "../../node_modules/@types/node/url.d.ts"
847 | ],
848 | "../../node_modules/@types/node/index.d.ts": [
849 | "../../node_modules/@types/node/base.d.ts"
850 | ],
851 | "../../node_modules/@types/node/inspector.d.ts": [
852 | "../../node_modules/@types/node/events.d.ts"
853 | ],
854 | "../../node_modules/@types/node/module.d.ts": [
855 | "../../node_modules/@types/node/url.d.ts"
856 | ],
857 | "../../node_modules/@types/node/net.d.ts": [
858 | "../../node_modules/@types/node/dns.d.ts",
859 | "../../node_modules/@types/node/events.d.ts",
860 | "../../node_modules/@types/node/stream.d.ts"
861 | ],
862 | "../../node_modules/@types/node/perf_hooks.d.ts": [
863 | "../../node_modules/@types/node/async_hooks.d.ts"
864 | ],
865 | "../../node_modules/@types/node/process.d.ts": [
866 | "../../node_modules/@types/node/tty.d.ts"
867 | ],
868 | "../../node_modules/@types/node/readline.d.ts": [
869 | "../../node_modules/@types/node/events.d.ts",
870 | "../../node_modules/@types/node/stream.d.ts"
871 | ],
872 | "../../node_modules/@types/node/repl.d.ts": [
873 | "../../node_modules/@types/node/readline.d.ts",
874 | "../../node_modules/@types/node/util.d.ts",
875 | "../../node_modules/@types/node/vm.d.ts"
876 | ],
877 | "../../node_modules/@types/node/stream.d.ts": [
878 | "../../node_modules/@types/node/events.d.ts"
879 | ],
880 | "../../node_modules/@types/node/tls.d.ts": [
881 | "../../node_modules/@types/node/crypto.d.ts",
882 | "../../node_modules/@types/node/dns.d.ts",
883 | "../../node_modules/@types/node/net.d.ts",
884 | "../../node_modules/@types/node/stream.d.ts"
885 | ],
886 | "../../node_modules/@types/node/ts3.4/base.d.ts": [
887 | "../../node_modules/@types/node/async_hooks.d.ts",
888 | "../../node_modules/@types/node/buffer.d.ts",
889 | "../../node_modules/@types/node/child_process.d.ts",
890 | "../../node_modules/@types/node/cluster.d.ts",
891 | "../../node_modules/@types/node/console.d.ts",
892 | "../../node_modules/@types/node/constants.d.ts",
893 | "../../node_modules/@types/node/crypto.d.ts",
894 | "../../node_modules/@types/node/dgram.d.ts",
895 | "../../node_modules/@types/node/dns.d.ts",
896 | "../../node_modules/@types/node/domain.d.ts",
897 | "../../node_modules/@types/node/events.d.ts",
898 | "../../node_modules/@types/node/fs.d.ts",
899 | "../../node_modules/@types/node/fs/promises.d.ts",
900 | "../../node_modules/@types/node/globals.d.ts",
901 | "../../node_modules/@types/node/http.d.ts",
902 | "../../node_modules/@types/node/http2.d.ts",
903 | "../../node_modules/@types/node/https.d.ts",
904 | "../../node_modules/@types/node/inspector.d.ts",
905 | "../../node_modules/@types/node/module.d.ts",
906 | "../../node_modules/@types/node/net.d.ts",
907 | "../../node_modules/@types/node/os.d.ts",
908 | "../../node_modules/@types/node/path.d.ts",
909 | "../../node_modules/@types/node/perf_hooks.d.ts",
910 | "../../node_modules/@types/node/process.d.ts",
911 | "../../node_modules/@types/node/punycode.d.ts",
912 | "../../node_modules/@types/node/querystring.d.ts",
913 | "../../node_modules/@types/node/readline.d.ts",
914 | "../../node_modules/@types/node/repl.d.ts",
915 | "../../node_modules/@types/node/stream.d.ts",
916 | "../../node_modules/@types/node/string_decoder.d.ts",
917 | "../../node_modules/@types/node/timers.d.ts",
918 | "../../node_modules/@types/node/tls.d.ts",
919 | "../../node_modules/@types/node/trace_events.d.ts",
920 | "../../node_modules/@types/node/tty.d.ts",
921 | "../../node_modules/@types/node/url.d.ts",
922 | "../../node_modules/@types/node/util.d.ts",
923 | "../../node_modules/@types/node/v8.d.ts",
924 | "../../node_modules/@types/node/vm.d.ts",
925 | "../../node_modules/@types/node/worker_threads.d.ts",
926 | "../../node_modules/@types/node/zlib.d.ts"
927 | ],
928 | "../../node_modules/@types/node/ts3.6/base.d.ts": [
929 | "../../node_modules/@types/node/globals.global.d.ts",
930 | "../../node_modules/@types/node/ts3.4/base.d.ts",
931 | "../../node_modules/@types/node/wasi.d.ts"
932 | ],
933 | "../../node_modules/@types/node/tty.d.ts": [
934 | "../../node_modules/@types/node/net.d.ts"
935 | ],
936 | "../../node_modules/@types/node/url.d.ts": [
937 | "../../node_modules/@types/node/querystring.d.ts"
938 | ],
939 | "../../node_modules/@types/node/v8.d.ts": [
940 | "../../node_modules/@types/node/stream.d.ts"
941 | ],
942 | "../../node_modules/@types/node/worker_threads.d.ts": [
943 | "../../node_modules/@types/node/events.d.ts",
944 | "../../node_modules/@types/node/fs/promises.d.ts",
945 | "../../node_modules/@types/node/stream.d.ts",
946 | "../../node_modules/@types/node/url.d.ts",
947 | "../../node_modules/@types/node/vm.d.ts"
948 | ],
949 | "../../node_modules/@types/node/zlib.d.ts": [
950 | "../../node_modules/@types/node/stream.d.ts"
951 | ],
952 | "../../node_modules/@types/yargs/index.d.ts": [
953 | "../../node_modules/@types/yargs-parser/index.d.ts"
954 | ],
955 | "../../node_modules/jest-diff/build/difflines.d.ts": [
956 | "../../node_modules/jest-diff/build/cleanupsemantic.d.ts",
957 | "../../node_modules/jest-diff/build/types.d.ts"
958 | ],
959 | "../../node_modules/jest-diff/build/index.d.ts": [
960 | "../../node_modules/jest-diff/build/cleanupsemantic.d.ts",
961 | "../../node_modules/jest-diff/build/difflines.d.ts",
962 | "../../node_modules/jest-diff/build/printdiffs.d.ts",
963 | "../../node_modules/jest-diff/build/types.d.ts"
964 | ],
965 | "../../node_modules/jest-diff/build/printdiffs.d.ts": [
966 | "../../node_modules/jest-diff/build/cleanupsemantic.d.ts",
967 | "../../node_modules/jest-diff/build/types.d.ts"
968 | ],
969 | "../../node_modules/pretty-format/build/index.d.ts": [
970 | "../../node_modules/pretty-format/build/types.d.ts"
971 | ]
972 | },
973 | "semanticDiagnosticsPerFile": [
974 | "./index.ts",
975 | "../../node_modules/@babel/parser/typings/babel-parser.d.ts",
976 | "../../node_modules/@babel/types/lib/index.d.ts",
977 | "../../node_modules/@types/babel__core/index.d.ts",
978 | "../../node_modules/@types/babel__generator/index.d.ts",
979 | "../../node_modules/@types/babel__template/index.d.ts",
980 | "../../node_modules/@types/babel__traverse/index.d.ts",
981 | "../../node_modules/@types/graceful-fs/index.d.ts",
982 | "../../node_modules/@types/istanbul-lib-coverage/index.d.ts",
983 | "../../node_modules/@types/istanbul-lib-report/index.d.ts",
984 | "../../node_modules/@types/istanbul-reports/index.d.ts",
985 | "../../node_modules/@types/jest/index.d.ts",
986 | "../../node_modules/@types/node/assert.d.ts",
987 | "../../node_modules/@types/node/async_hooks.d.ts",
988 | "../../node_modules/@types/node/base.d.ts",
989 | "../../node_modules/@types/node/buffer.d.ts",
990 | "../../node_modules/@types/node/child_process.d.ts",
991 | "../../node_modules/@types/node/cluster.d.ts",
992 | "../../node_modules/@types/node/console.d.ts",
993 | "../../node_modules/@types/node/constants.d.ts",
994 | "../../node_modules/@types/node/crypto.d.ts",
995 | "../../node_modules/@types/node/dgram.d.ts",
996 | "../../node_modules/@types/node/dns.d.ts",
997 | "../../node_modules/@types/node/domain.d.ts",
998 | "../../node_modules/@types/node/events.d.ts",
999 | "../../node_modules/@types/node/fs.d.ts",
1000 | "../../node_modules/@types/node/fs/promises.d.ts",
1001 | "../../node_modules/@types/node/globals.d.ts",
1002 | "../../node_modules/@types/node/globals.global.d.ts",
1003 | "../../node_modules/@types/node/http.d.ts",
1004 | "../../node_modules/@types/node/http2.d.ts",
1005 | "../../node_modules/@types/node/https.d.ts",
1006 | "../../node_modules/@types/node/index.d.ts",
1007 | "../../node_modules/@types/node/inspector.d.ts",
1008 | "../../node_modules/@types/node/module.d.ts",
1009 | "../../node_modules/@types/node/net.d.ts",
1010 | "../../node_modules/@types/node/os.d.ts",
1011 | "../../node_modules/@types/node/path.d.ts",
1012 | "../../node_modules/@types/node/perf_hooks.d.ts",
1013 | "../../node_modules/@types/node/process.d.ts",
1014 | "../../node_modules/@types/node/punycode.d.ts",
1015 | "../../node_modules/@types/node/querystring.d.ts",
1016 | "../../node_modules/@types/node/readline.d.ts",
1017 | "../../node_modules/@types/node/repl.d.ts",
1018 | "../../node_modules/@types/node/stream.d.ts",
1019 | "../../node_modules/@types/node/string_decoder.d.ts",
1020 | "../../node_modules/@types/node/timers.d.ts",
1021 | "../../node_modules/@types/node/tls.d.ts",
1022 | "../../node_modules/@types/node/trace_events.d.ts",
1023 | "../../node_modules/@types/node/ts3.4/base.d.ts",
1024 | "../../node_modules/@types/node/ts3.6/base.d.ts",
1025 | "../../node_modules/@types/node/tty.d.ts",
1026 | "../../node_modules/@types/node/url.d.ts",
1027 | "../../node_modules/@types/node/util.d.ts",
1028 | "../../node_modules/@types/node/v8.d.ts",
1029 | "../../node_modules/@types/node/vm.d.ts",
1030 | "../../node_modules/@types/node/wasi.d.ts",
1031 | "../../node_modules/@types/node/worker_threads.d.ts",
1032 | "../../node_modules/@types/node/zlib.d.ts",
1033 | "../../node_modules/@types/normalize-package-data/index.d.ts",
1034 | "../../node_modules/@types/prettier/index.d.ts",
1035 | "../../node_modules/@types/stack-utils/index.d.ts",
1036 | "../../node_modules/@types/yargs-parser/index.d.ts",
1037 | "../../node_modules/@types/yargs/index.d.ts",
1038 | "../../node_modules/jest-diff/build/cleanupsemantic.d.ts",
1039 | "../../node_modules/jest-diff/build/difflines.d.ts",
1040 | "../../node_modules/jest-diff/build/index.d.ts",
1041 | "../../node_modules/jest-diff/build/printdiffs.d.ts",
1042 | "../../node_modules/jest-diff/build/types.d.ts",
1043 | "../../node_modules/pretty-format/build/index.d.ts",
1044 | "../../node_modules/pretty-format/build/types.d.ts",
1045 | "../../node_modules/typescript/lib/lib.dom.d.ts",
1046 | "../../node_modules/typescript/lib/lib.es2015.collection.d.ts",
1047 | "../../node_modules/typescript/lib/lib.es2015.core.d.ts",
1048 | "../../node_modules/typescript/lib/lib.es2015.d.ts",
1049 | "../../node_modules/typescript/lib/lib.es2015.generator.d.ts",
1050 | "../../node_modules/typescript/lib/lib.es2015.iterable.d.ts",
1051 | "../../node_modules/typescript/lib/lib.es2015.promise.d.ts",
1052 | "../../node_modules/typescript/lib/lib.es2015.proxy.d.ts",
1053 | "../../node_modules/typescript/lib/lib.es2015.reflect.d.ts",
1054 | "../../node_modules/typescript/lib/lib.es2015.symbol.d.ts",
1055 | "../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts",
1056 | "../../node_modules/typescript/lib/lib.es2016.array.include.d.ts",
1057 | "../../node_modules/typescript/lib/lib.es2016.d.ts",
1058 | "../../node_modules/typescript/lib/lib.es2017.d.ts",
1059 | "../../node_modules/typescript/lib/lib.es2017.intl.d.ts",
1060 | "../../node_modules/typescript/lib/lib.es2017.object.d.ts",
1061 | "../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts",
1062 | "../../node_modules/typescript/lib/lib.es2017.string.d.ts",
1063 | "../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts",
1064 | "../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts",
1065 | "../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts",
1066 | "../../node_modules/typescript/lib/lib.es2018.d.ts",
1067 | "../../node_modules/typescript/lib/lib.es2018.intl.d.ts",
1068 | "../../node_modules/typescript/lib/lib.es2018.promise.d.ts",
1069 | "../../node_modules/typescript/lib/lib.es2018.regexp.d.ts",
1070 | "../../node_modules/typescript/lib/lib.es2020.bigint.d.ts",
1071 | "../../node_modules/typescript/lib/lib.es5.d.ts",
1072 | "../../node_modules/typescript/lib/lib.esnext.intl.d.ts"
1073 | ]
1074 | },
1075 | "version": "4.1.3"
1076 | }
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/advanced.ts:
--------------------------------------------------------------------------------
1 | export type PartialRecord = {
2 | [P in K]?: T;
3 | };
4 |
5 | interface SignupFormState {
6 | email: string;
7 | name: string;
8 | }
9 |
10 | interface ActionPayload {
11 | key: keyof SignupFormState;
12 | value: string;
13 | }
14 |
15 | const update1: ActionPayload = {
16 | key: "email",
17 | value: "hello@gmail.com",
18 | };
19 |
20 | type actionPayloadKeys = keyof typeof update1;
21 |
22 | type Point2d = { x: number; y: number };
23 |
24 | type NominalTyped = Type & { __type: Brand };
25 |
26 | type Point3d = NominalTyped;
27 |
28 | function distance1(first: Point2d, second: Point2d) {
29 | return Math.sqrt(
30 | Math.pow(first.x - second.x, 2) + Math.pow(first.y - second.y, 2)
31 | );
32 | }
33 | distance1({ x: 1, y: 2 }, { x: 3, y: 4 });
34 |
35 | function distance2(
36 | first: NominalTyped,
37 | second: NominalTyped
38 | ) {
39 | return Math.sqrt(
40 | Math.pow(first.x - second.x, 2) + Math.pow(first.y - second.y, 2)
41 | );
42 | }
43 |
44 | class User {
45 | private static readonly __type: unique symbol = Symbol();
46 | name: string;
47 | constructor(name: string) {
48 | this.name = name;
49 | }
50 | }
51 | type Account = {
52 | name: string;
53 | };
54 | function printAccountName(o: User) {
55 | console.log(o.name);
56 | }
57 | printAccountName(new User("Theo"));
58 | // printAccountName({name: "Alex"}) // Fail to typecheck
59 |
60 | type PPSNumber = {
61 | number: string;
62 | };
63 | type NameOrPPSNumber = T extends number
64 | ? PPSNumber
65 | : string;
66 |
67 | const loginInfo: NameOrPPSNumber<1> = {
68 | number: "123",
69 | };
70 |
71 | interface Box {
72 | value: T;
73 | }
74 |
75 | type UnpackBox = A extends Box ? E : A;
76 |
77 | type intStash = UnpackBox<{ value: 10 }>;
78 | type stringStash = UnpackBox<{ value: "123" }>;
79 | type booleanStash = UnpackBox;
80 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/deno/index.ts:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import { listenAndServe } from "https://deno.land/std@0.88.0/http/server.ts";
3 |
4 | const serverConfig = {
5 | port: 8000,
6 | };
7 |
8 | listenAndServe(serverConfig, (req) => {
9 | req.respond({ body: "Hello World\n" });
10 | });
11 |
12 | console.info(`Server started at http://localhost:8000`);
13 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/express/app.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import bodyParser from "body-parser";
3 | import morgan from "morgan";
4 |
5 | const app = express();
6 | const logger = morgan("combined");
7 |
8 | app.use(
9 | bodyParser.urlencoded({
10 | extended: true,
11 | })
12 | );
13 | app.use(bodyParser.json());
14 | app.use(logger);
15 |
16 | export default app;
17 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/express/container.ts:
--------------------------------------------------------------------------------
1 | import { Container } from "inversify";
2 |
3 | import "./health.controller";
4 |
5 | // set up container
6 | const container = new Container();
7 |
8 | // set up bindings
9 |
10 | export default container;
11 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/express/health.controller.ts:
--------------------------------------------------------------------------------
1 | import { injectable, inject } from "inversify";
2 | import {
3 | controller,
4 | httpGet,
5 | BaseHttpController,
6 | } from "inversify-express-utils";
7 |
8 | @controller("/health")
9 | export class HealthController extends BaseHttpController {
10 | @httpGet("/")
11 | public async get() {
12 | return this.ok("All good!");
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/express/server.ts:
--------------------------------------------------------------------------------
1 | import "reflect-metadata";
2 | import { interfaces, InversifyExpressServer } from "inversify-express-utils";
3 |
4 | import app from "./app";
5 | import container from "./container";
6 |
7 | const port = process.env.PORT || 3000;
8 |
9 | let server = new InversifyExpressServer(container, null, null, app);
10 | server.build().listen(port);
11 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/node-error/index.ts:
--------------------------------------------------------------------------------
1 | export class AppError extends Error {
2 | public readonly isOperational: boolean;
3 |
4 | constructor(description: string, isOperational: boolean) {
5 | super(description);
6 | this.name = this.constructor.name;
7 | this.isOperational = isOperational;
8 | Error.captureStackTrace(this);
9 | }
10 | }
11 |
12 | function isAppError(error: Error | AppError): error is AppError {
13 | return (error as AppError).isOperational !== undefined;
14 | }
15 |
16 | class ErrorManagementService {
17 | public handleError(err: Error): void {
18 | console.log("Handling error:", err.message);
19 | }
20 |
21 | public isTrusted(error: Error) {
22 | if (isAppError(error)) {
23 | return error.isOperational;
24 | }
25 | return false;
26 | }
27 | }
28 |
29 | const errorManagementService = new ErrorManagementService();
30 |
31 | process.on("uncaughtException", (error: Error) => {
32 | errorManagementService.handleError(error);
33 | if (!errorManagementService.isTrusted(error)) {
34 | console.log("Exiting because of error");
35 | process.exit(1);
36 | }
37 | });
38 |
39 | throw new AppError("Invalid use case", true); // Untrusted - Exit
40 | // throw new Error("Invalid use case"); // Untrusted - Exit
41 | // throw new AppError("Invalid use case", true); // Trusted - continue
42 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/oop.ts:
--------------------------------------------------------------------------------
1 | interface RestApiClient {
2 | getAll(): Promise;
3 | getOne(id: string): Promise;
4 | }
5 |
6 | interface Site {
7 | name: string;
8 | }
9 |
10 | class SitesApiClient implements RestApiClient {
11 | getAll() {
12 | const res: Site[] = [{ name: "website1" }];
13 | return Promise.resolve(res);
14 | }
15 | getOne(id: string) {
16 | return Promise.resolve({ name: "website1" });
17 | }
18 | }
19 |
20 | class EventAction {
21 | trigger(delay: number = 0) {
22 | console.log(`Event triggered in ${delay}s.`);
23 | }
24 | }
25 | class NotificationEvent extends EventAction {
26 | sendEmail() {
27 | console.log("Sending Email");
28 | }
29 | }
30 | const ev = new NotificationEvent();
31 | ev.trigger();
32 | ev.sendEmail();
33 | ev.trigger(10);
34 |
35 | class A {
36 | constructor() {
37 | this.subClassCheck();
38 | }
39 |
40 | private subClassCheck(): never | void {
41 | if (Object.getPrototypeOf(this) !== A.prototype) {
42 | throw new Error("Cannot extend this class.");
43 | }
44 | }
45 | }
46 |
47 | class B extends A {}
48 |
49 | let a = new A(); // OK
50 | // let b = new B(); // fail
51 |
52 | class User {
53 | #name: string;
54 |
55 | constructor(name: string) {
56 | this.#name = name;
57 | }
58 |
59 | greet() {
60 | console.log(`User: ${this.#name}!`);
61 | }
62 | }
63 |
64 | const theo = new User("Theo");
65 | // theo.#name; // cannot access private field
66 |
67 | class Component {
68 | onInit(): void {
69 | console.log("Called from Component");
70 | }
71 | }
72 |
73 | class ReactComponent extends Component {
74 | onInit(): void {
75 | super.onInit();
76 | console.log("Called from React Component");
77 | }
78 | }
79 |
80 | const c = new ReactComponent();
81 | c.onInit(); // logs "Called from React Component"
82 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/partial.ts:
--------------------------------------------------------------------------------
1 | enum PRIORITY {
2 | DEFAULT,
3 |
4 | LOW,
5 |
6 | HIGH,
7 | }
8 |
9 | interface TodoItemProps {
10 | title: string;
11 |
12 | description: string;
13 |
14 | priority: PRIORITY;
15 | }
16 |
17 | class TodoItem {
18 | description?: string;
19 |
20 | title = "Default item title";
21 |
22 | priority = PRIORITY.DEFAULT;
23 |
24 | constructor(todoItemProps: Partial = {}) {
25 | Object.assign(this, todoItemProps);
26 | }
27 | }
28 |
29 | const item = new TodoItem({ description: "Some description" });
30 |
31 | console.debug(item.description); // prints "Some description"
32 |
33 | console.debug(item.title); // prints "Some description"
34 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/react/app.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as ReactDOM from "react-dom";
3 |
4 | interface AppProps {
5 | greeting: string;
6 | }
7 |
8 | const App: React.FC = ({ greeting = "Hello" }) => {
9 | return (
10 |
11 |
{greeting}
12 |
13 | );
14 | };
15 |
16 | ReactDOM.render(
17 | ,
18 | document.getElementById("app")
19 | );
20 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Document
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "moduleResolution": "node",
5 | "sourceMap": true,
6 | "jsx": "react",
7 | "strict": true,
8 | },
9 | "include": [
10 | "**/*.ts",
11 | "**/*.tsx"
12 | ],
13 | "exclude": [
14 | "node_modules"
15 | ]
16 | }
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/react/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | module.exports = {
4 | entry: path.resolve(__dirname, "./app.tsx"),
5 | devtool: "inline-source-map",
6 | module: {
7 | rules: [
8 | {
9 | test: /\.tsx?$/,
10 | use: "ts-loader",
11 | exclude: /node_modules/,
12 | },
13 | ],
14 | },
15 | resolve: {
16 | extensions: [".tsx", ".ts", ".js"],
17 | },
18 | output: {
19 | filename: "index.js",
20 | path: path.resolve(__dirname, "./"),
21 | },
22 | devServer: {
23 | contentBase: path.join(__dirname, "./"),
24 | compress: true,
25 | port: 9000,
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | // compiler options
5 | "composite": false,
6 | "allowJs": true,
7 | "noImplicitAny": false,
8 | "target": "ES2015"
9 | },
10 | }
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/utility.ts:
--------------------------------------------------------------------------------
1 | import { HTMLAttributes } from "react";
2 |
3 | const serviceConfig: Record = {
4 | port: 3000,
5 | basePath: "http://localhost",
6 | enableStripePayments: false,
7 | };
8 |
9 | console.log(serviceConfig.port); // prints 3000
10 |
11 | serviceConfig.enablePayments;
12 |
13 | type ServiceConfigParams = "port" | "basePath" | "enableStripePayments";
14 | const serviceConfigChecked: Record<
15 | ServiceConfigParams,
16 | string | number | boolean
17 | > = {
18 | port: 3000,
19 | basePath: "http://localhost",
20 | enableStripePayments: false,
21 | };
22 |
23 | console.log(serviceConfig.basePath); // prints http://localhost
24 |
25 | enum PRIORITY {
26 | DEFAULT,
27 | LOW,
28 | HIGH,
29 | }
30 | interface TodoItemProps {
31 | title: string;
32 | description: string;
33 | priority: PRIORITY;
34 | }
35 | class TodoItem {
36 | description?: string;
37 | title = "Default item title";
38 | priority = PRIORITY.DEFAULT;
39 | constructor(todoItemProps: Partial = {}) {
40 | Object.assign(this, todoItemProps);
41 | }
42 | }
43 |
44 | const item = new TodoItem({ description: "Some description" });
45 | console.debug(item.description); // prints "Some description"
46 | console.debug(item.title); // prints "Some description"
47 |
48 | type OriginalTodoItemProps = Required>; // type is same as TodoItemProps
49 |
50 | type ButtonProps = Pick<
51 | HTMLAttributes,
52 | "onClick" | "onSubmit" | "className" | "onFocus"
53 | >;
54 |
55 | type OriginalThemProps = {
56 | colors: string[];
57 | elevations: string[];
58 | margins: string[];
59 | defaultTypography: string;
60 | };
61 | type CustomThemeProps = {
62 | colors: Set;
63 | };
64 | type ThemeProps = Omit & {
65 | colors?: CustomThemeProps;
66 | };
67 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/webpack/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Document
5 |
6 |
7 |
8 | Typescript 4 Design Patterns
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/webpack/index.js:
--------------------------------------------------------------------------------
1 | /******/ (() => { // webpackBootstrap
2 | /******/ "use strict";
3 | var __webpack_exports__ = {};
4 | /******/ })()
5 | ;
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/webpack/index.ts:
--------------------------------------------------------------------------------
1 | const par = document.getElementsByClassName("paragraph")[0];
2 |
3 | const span = document.createElement("span");
4 | span.textContent = "This is a text we added dynamically";
5 | par?.appendChild(span);
6 |
7 | const button = document.querySelector("button");
8 | button?.addEventListener("click", () => {
9 | window.alert("Did you Clicked the Submit Button");
10 | });
11 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/webpack/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es5",
5 | "esModuleInterop": true
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/chapters/chapter-2_Core_Principles_and_use_cases/webpack/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | module.exports = {
4 | entry: path.resolve(__dirname, "./index.ts"),
5 | devtool: "inline-source-map",
6 | module: {
7 | rules: [
8 | {
9 | test: /\.tsx?$/,
10 | use: "ts-loader",
11 | exclude: /node_modules/,
12 | },
13 | ],
14 | },
15 | resolve: {
16 | extensions: [".tsx", ".ts", ".js"],
17 | },
18 | output: {
19 | filename: "index.js",
20 | path: path.resolve(__dirname, "./"),
21 | },
22 | devServer: {
23 | contentBase: path.join(__dirname, "./"),
24 | compress: true,
25 | port: 9000,
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/TypeScript-4-Design-Patterns-and-Best-Practices/794888bd4c351b9565e01828440e3d0cf06d26c6/chapters/chapter-3_Creational_Design_Patterns/.gitkeep
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/AbstractFactory.test.ts:
--------------------------------------------------------------------------------
1 | import {
2 | HTMLWebsitePageFactory,
3 | WebsitePageFactory,
4 | HTMLContent,
5 | HTMLHeader,
6 | HTMLFooter,
7 | } from "./AbstractFactory";
8 |
9 | const wpf: WebsitePageFactory = new HTMLWebsitePageFactory();
10 | test("it creates an HTML Content type", () => {
11 | const content = wpf.createContent("Content");
12 | expect(content).toBeInstanceOf(HTMLContent);
13 | expect(content.content).toBe("Content");
14 | });
15 | test("it creates an HTML Header type", () => {
16 | const header = wpf.createHeader("Header");
17 | expect(header).toBeInstanceOf(HTMLHeader);
18 | expect(header.content).toBe("Header");
19 | });
20 | test("it creates an HTML Footer type", () => {
21 | const footer = wpf.createFooter("Footer");
22 | expect(footer).toBeInstanceOf(HTMLFooter);
23 | expect(footer.content).toBe("");
24 | });
25 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/AbstractFactory.ts:
--------------------------------------------------------------------------------
1 | export interface WebsitePageFactory {
2 | createHeader(text: string): Header;
3 | createContent(text: string): Content;
4 | createFooter(text: string): Footer;
5 | }
6 |
7 | interface Header {
8 | content: string;
9 | }
10 |
11 | interface Content {
12 | content: string;
13 | }
14 |
15 | interface Footer {
16 | content: string;
17 | }
18 |
19 | export class HTMLWebsitePageFactory implements WebsitePageFactory {
20 | createHeader(text: string): HTMLHeader {
21 | return new HTMLHeader(text);
22 | }
23 | createContent(text: string): HTMLContent {
24 | return new HTMLContent(text);
25 | }
26 | createFooter(text: string): HTMLFooter {
27 | return new HTMLFooter(text);
28 | }
29 | }
30 |
31 | export class HTMLHeader implements Header {
32 | content: string;
33 | constructor(text: string) {
34 | this.content = `${text}`;
35 | }
36 | }
37 |
38 | export class HTMLContent implements Content {
39 | content: string;
40 | constructor(text: string) {
41 | this.content = `${text}`;
42 | }
43 | }
44 |
45 | export class HTMLFooter implements Footer {
46 | content: string;
47 | constructor(text: string) {
48 | this.content = ``;
49 | }
50 | }
51 |
52 | const wpf: WebsitePageFactory = new HTMLWebsitePageFactory();
53 | console.log(wpf.createContent("Content").content);
54 | console.log(wpf.createHeader("Header").content);
55 | console.log(wpf.createFooter("Footer").content);
56 |
57 | type Circle = string;
58 | type CircleProps = {
59 | cx: number;
60 | cy: number;
61 | radius: number;
62 | };
63 | type RectangleProps = {
64 | x1: number;
65 | y1: number;
66 | width: number;
67 | height: number;
68 | };
69 |
70 | interface BrowserGraphicsFactory {
71 | drawCircle(props: CircleProps): Circle;
72 | drawRectangle(props: RectangleProps): Circle;
73 | }
74 |
75 | // class CanvasGraphicsFactory implements BrowserGraphicsFactory {
76 |
77 | // }
78 |
79 | // class SVGGraphicsFactory implements BrowserGraphicsFactory {
80 |
81 | // }
82 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/FactoryMethod.test.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Weapon,
3 | LongBow,
4 | LongSword,
5 | LongBowFactory,
6 | LongSwordFactory,
7 | } from "./FactoryMethod";
8 |
9 | let lbf: LongBowFactory;
10 | let lsf: LongSwordFactory;
11 | beforeEach(() => {
12 | lbf = new LongBowFactory();
13 | lsf = new LongSwordFactory();
14 | });
15 |
16 | test("it creates a LongBow type using the factory", () => {
17 | const weapon = lbf.create();
18 | expect(weapon).toBeInstanceOf(LongBow);
19 | });
20 |
21 | test("it creates a LongSword type using the factory", () => {
22 | const weapon = lsf.create();
23 | expect(weapon).toBeInstanceOf(LongSword);
24 | });
25 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/FactoryMethod.ts:
--------------------------------------------------------------------------------
1 | export interface Weapon {
2 | getName(): string;
3 | getDamage(): number;
4 | getRange(): number;
5 | }
6 |
7 | export class LongSword implements Weapon {
8 | getName(): string {
9 | return "LongSword";
10 | }
11 | getDamage(): number {
12 | return 10;
13 | }
14 | getRange(): number {
15 | return 2;
16 | }
17 | }
18 |
19 | export class LongBow implements Weapon {
20 | getName(): string {
21 | return "LongBow";
22 | }
23 | getDamage(): number {
24 | return 8;
25 | }
26 | getRange(): number {
27 | return 16;
28 | }
29 | }
30 |
31 | interface WeaponFactory {
32 | create(): Weapon;
33 | }
34 |
35 | export class LongSwordFactory implements WeaponFactory {
36 | create(): Weapon {
37 | return new LongSword();
38 | }
39 | }
40 | export class LongBowFactory implements WeaponFactory {
41 | create(): Weapon {
42 | return new LongBow();
43 | }
44 | }
45 |
46 | const lbf = new LongBowFactory();
47 | const lsf = new LongSwordFactory();
48 | const factories: WeaponFactory[] = [lbf, lsf, lbf];
49 | factories.forEach((f: WeaponFactory) => {
50 | console.debug(f.create());
51 | });
52 |
53 | const enum WeaponType {
54 | LONGBOW,
55 | LONGSWORD,
56 | }
57 |
58 | class WeaponCreator {
59 | create(weaponType: WeaponType): Weapon {
60 | switch (weaponType) {
61 | case WeaponType.LONGBOW: {
62 | return new LongBow();
63 | break;
64 | }
65 | case WeaponType.LONGSWORD: {
66 | return new LongSword();
67 | break;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/FactoryMethodType.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/TypeScript-4-Design-Patterns-and-Best-Practices/794888bd4c351b9565e01828440e3d0cf06d26c6/chapters/chapter-3_Creational_Design_Patterns/FactoryMethodType.ts
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/InversifySingleton.ts:
--------------------------------------------------------------------------------
1 | import "reflect-metadata";
2 | import { injectable, Container } from "inversify";
3 |
4 | interface UsersApiService {
5 | getUsers(): Promise;
6 | }
7 |
8 | let TYPES = {
9 | UsersApiService: Symbol("UsersApiService"),
10 | };
11 |
12 | @injectable()
13 | class UsersApiServiceImpl implements UsersApiService {
14 | getUsers(): Promise {
15 | return Promise.resolve(["Alex", "John", "Sarah"]);
16 | }
17 | }
18 |
19 | // set up container
20 | const container = new Container();
21 | // set up bindings
22 | container
23 | .bind(TYPES.UsersApiService)
24 | .to(UsersApiServiceImpl)
25 | .inSingletonScope();
26 |
27 | container
28 | .get(TYPES.UsersApiService)
29 | .getUsers()
30 | .then((res) => console.log(res));
31 | export default container;
32 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/ModuleSingleton.ts:
--------------------------------------------------------------------------------
1 | class ApiServiceSingleton {}
2 |
3 | export default new ApiServiceSingleton();
4 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/ParametricSingleton.ts:
--------------------------------------------------------------------------------
1 | export class ParametricSingleton {
2 | private param: string;
3 | // Stores the singletons instances
4 | private static instances: Map;
5 | // Prevents creation of new instances
6 | private constructor(param: string) {
7 | this.param = param;
8 | }
9 | // Method to retrieve instance
10 | static getInstance(param: string) {
11 | if (!ParametricSingleton.instances.has(param)) {
12 | ParametricSingleton.instances.set(param, new ParametricSingleton(param));
13 | }
14 | return ParametricSingleton.instances.get(param);
15 | }
16 | }
17 |
18 | export default ParametricSingleton;
19 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/Prototype.test.ts:
--------------------------------------------------------------------------------
1 | import { Warrior, Wizard, HeroPrototype } from "./Prototype";
2 |
3 | test("it creates a Wizard from a prototype", () => {
4 | const wiz = new Wizard("Theo");
5 | expect(wiz.clone()).toBeInstanceOf(Wizard);
6 | expect(JSON.stringify(wiz.clone())).toBe(
7 | '{"name":"Unknown","spells":[],"health":100}'
8 | );
9 | });
10 | test("it creates a Warrior from a prototype", () => {
11 | const war = new Warrior("Alex");
12 | expect(war.clone()).toBeInstanceOf(Warrior);
13 | expect(JSON.stringify(war.clone())).toBe(
14 | '{"name":"Alex","weapon":"Bare Hands","health":150}'
15 | );
16 | });
17 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/Prototype.ts:
--------------------------------------------------------------------------------
1 | export interface HeroPrototype {
2 | clone(): HeroPrototype;
3 | }
4 |
5 | export interface Spell {
6 | name: string;
7 | }
8 |
9 | export class Wizard implements HeroPrototype {
10 | private spells: Spell[];
11 | private health: number;
12 | constructor(private name: string) {
13 | this.spells = [];
14 | this.health = 100;
15 | }
16 |
17 | clone(): Wizard {
18 | const cloned = Object.create(Wizard.prototype || null);
19 | Object.getOwnPropertyNames(this).map((key: string) => {
20 | if (key === "name") {
21 | cloned[key] = "Unknown";
22 | } else {
23 | cloned[key] = this[key];
24 | }
25 | });
26 |
27 | return cloned;
28 | }
29 | }
30 |
31 | export class Warrior implements HeroPrototype {
32 | private weapon: string;
33 | private health: number;
34 | constructor(private name: string) {
35 | this.weapon = "Dagger";
36 | this.health = 150;
37 | }
38 |
39 | clone(): Warrior {
40 | const cloned = Object.create(Warrior.prototype || null);
41 | Object.getOwnPropertyNames(this).map((key: string) => {
42 | if (key === "weapon") {
43 | cloned[key] = "Bare Hands";
44 | } else {
45 | cloned[key] = this[key];
46 | }
47 | });
48 |
49 | return cloned;
50 | }
51 | }
52 |
53 | let wiz: HeroPrototype = new Wizard("Theo");
54 | let war: HeroPrototype = new Warrior("Mike");
55 | console.debug(wiz.clone());
56 | console.debug(war.clone());
57 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/ProxyBuilder.ts:
--------------------------------------------------------------------------------
1 | export type Builder = {
2 | [k in keyof T]-?: (arg: T[k]) => Builder;
3 | } & {
4 | build(): T;
5 | };
6 |
7 | export function ModelBuilder(): Builder {
8 | const built: Record = {};
9 | const builder = new Proxy(
10 | {},
11 | {
12 | get(target, prop) {
13 | if ("build" === prop) {
14 | return () => built;
15 | }
16 |
17 | return (x: unknown): unknown => {
18 | built[prop.toString()] = x;
19 | return builder;
20 | };
21 | },
22 | }
23 | );
24 |
25 | return builder as Builder;
26 | }
27 |
28 | interface UserInfo {
29 | id: number;
30 | userName: string;
31 | email: string;
32 | }
33 |
34 | const userInfo = ModelBuilder()
35 | .id(1)
36 | .userName("foo")
37 | .email("foo@bar.baz")
38 | .build();
39 |
40 | console.debug(userInfo);
41 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/UsersApiSingleton.ts:
--------------------------------------------------------------------------------
1 | export class UsersAPISingleton {
2 | private static instance: UsersAPISingleton;
3 | private constructor() {}
4 | static getInstance() {
5 | if (!UsersAPISingleton.instance) {
6 | UsersAPISingleton.instance = new UsersAPISingleton();
7 | }
8 |
9 | return UsersAPISingleton.instance;
10 | }
11 |
12 | getUsers(): Promise {
13 | return Promise.resolve(["Alex", "John", "Sarah"]);
14 | }
15 | }
16 |
17 | const usersPromise = UsersAPISingleton.getInstance().getUsers();
18 | usersPromise.then((res) => {
19 | console.log(res);
20 | });
21 |
22 | UsersAPISingleton.getInstance("/v1/users").getUsers();
23 | UsersAPISingleton.getInstance("/v2/users").getUsers();
24 |
25 | UsersAPISingleton.getInstance("/v1/users") ===
26 | UsersAPISingleton.getInstance("/v1/users");
27 | UsersAPISingleton.getInstance("/v1/users") !==
28 | UsersAPISingleton.getInstance("/v2/users");
29 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/WebsiteBuilder.test.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Website,
3 | PremiumWebsiteBuilder,
4 | WebsiteBuilder,
5 | } from "./WebsiteBuilder";
6 |
7 | let wb: WebsiteBuilder;
8 | beforeEach(() => {
9 | wb = new PremiumWebsiteBuilder();
10 | });
11 |
12 | test("PremiumWebsiteBuilder builds a premium website with the correct properties", () => {
13 | const website = wb
14 | .setName("example")
15 | .setHost("localhost")
16 | .setIsPremium(false)
17 | .setPort(3000)
18 | .build();
19 | expect(website.isPremium).toBeTruthy;
20 | expect(website.name).toBe("example");
21 | expect(website.host).toBe("localhost");
22 | expect(website.port).toBe(3000);
23 | });
24 |
25 | test("PremiumWebsiteBuilder order of steps does not have side effects", () => {
26 | const website = wb
27 | .setName("example")
28 | .setPort(3000)
29 | .setHost("localhost")
30 | .setIsPremium(false)
31 | .setName("example2")
32 | .build();
33 | expect(website.isPremium).toBeTruthy;
34 | expect(website.name).toBe("example2");
35 | expect(website.host).toBe("localhost");
36 | expect(website.port).toBe(3000);
37 | });
38 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/WebsiteBuilder.ts:
--------------------------------------------------------------------------------
1 | export class Website {
2 | constructor(
3 | public name?: string,
4 | public host?: string,
5 | public port?: number,
6 | public adminEmail?: string,
7 | public content?: string,
8 | public isPremium?: boolean
9 | ) {}
10 | }
11 |
12 | export interface WebsiteBuilder {
13 | setName(name: string): WebsiteBuilder;
14 | setHost(host: string): WebsiteBuilder;
15 | setPort(port: number): WebsiteBuilder;
16 | setAdminEmail(email: string): WebsiteBuilder;
17 | setContent(content: string): WebsiteBuilder;
18 | setIsPremium(isPremium: boolean): WebsiteBuilder;
19 | build(): Website;
20 | }
21 |
22 | export class PremiumWebsiteBuilder implements WebsiteBuilder {
23 | private website: Website;
24 | constructor() {
25 | this.website = new Website();
26 | this.clear();
27 | }
28 |
29 | setName(name: string): WebsiteBuilder {
30 | this.website.name = name;
31 | return this;
32 | }
33 |
34 | setHost(host: string): WebsiteBuilder {
35 | this.website.host = host;
36 | return this;
37 | }
38 |
39 | setPort(port: number): WebsiteBuilder {
40 | this.website.port = port;
41 | return this;
42 | }
43 |
44 | setAdminEmail(email: string): WebsiteBuilder {
45 | this.website.adminEmail = email;
46 | return this;
47 | }
48 |
49 | setContent(content: string): WebsiteBuilder {
50 | this.website.content = content;
51 | return this;
52 | }
53 |
54 | setIsPremium(): WebsiteBuilder {
55 | this.website.isPremium = true;
56 | return this;
57 | }
58 |
59 | build(): Website {
60 | const website = this.website;
61 | this.clear();
62 | return website;
63 | }
64 |
65 | clear(): void {
66 | this.website = new Website();
67 | this.website.isPremium = true;
68 | }
69 | }
70 |
71 | const wb = new PremiumWebsiteBuilder();
72 | wb.setName("example").setHost("localhost").setPort(3000);
73 |
74 | const website = wb.build();
75 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/singleton.test.ts:
--------------------------------------------------------------------------------
1 | import singleton from "./singleton";
2 |
3 | test("singleton is a Singleton", () => {
4 | expect(singleton.getInstance()).toBe(singleton.getInstance());
5 | });
6 |
--------------------------------------------------------------------------------
/chapters/chapter-3_Creational_Design_Patterns/singleton.ts:
--------------------------------------------------------------------------------
1 | export class Singleton {
2 | // Stores the singleton instance
3 | private static instance: Singleton;
4 | // Prevents creation of new instances
5 | private constructor() {}
6 | // Method to retrieve instance
7 | static getInstance() {
8 | if (!Singleton.instance) {
9 | Singleton.instance = new Singleton();
10 | }
11 | return Singleton.instance;
12 | }
13 | }
14 |
15 | export default Singleton;
16 |
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/TypeScript-4-Design-Patterns-and-Best-Practices/794888bd4c351b9565e01828440e3d0cf06d26c6/chapters/chapter-4_Structural_Design_Patterns/.gitkeep
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/Adapter.test.ts:
--------------------------------------------------------------------------------
1 | import { ActionSender, EventAdapter } from "./Adapter";
2 | import { mocked } from "ts-jest/utils";
3 | import { EventCreator } from "./EventCreator";
4 |
5 | jest.mock("./EventCreator", () => {
6 | return {
7 | EventCreator: jest.fn().mockImplementation(() => {
8 | return {
9 | sendEvent: jest.fn(),
10 | };
11 | }),
12 | };
13 | });
14 |
15 | describe("EventCreator", () => {
16 | const mockedEventCreator = mocked(EventCreator, true);
17 | beforeEach(() => {
18 | // Clears the record of calls to the mock constructor function and its methods
19 | mockedEventCreator.mockClear();
20 | });
21 |
22 | let ad: ActionSender;
23 | test("it calls the service function", () => {
24 | ad = new EventAdapter();
25 | ad.sendAction("action");
26 | expect(mockedEventCreator).toHaveBeenCalledTimes(1);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/Adapter.ts:
--------------------------------------------------------------------------------
1 | import {EventCreator} from "./EventCreator";
2 |
3 | export interface ActionSender {
4 | sendAction(action: string): Promise;
5 | }
6 |
7 | export class ActionCreator implements ActionSender {
8 | sendAction(action: string): Promise {
9 | return new Promise((resolve, reject) => {
10 | console.log("Event Created: ", action);
11 | resolve();
12 | });
13 | }
14 | }
15 |
16 | export interface EventSender {
17 | sendEvent(eventName: string): void;
18 | }
19 |
20 | export class EventAdapter implements ActionSender {
21 | eventSender: EventSender;
22 | constructor(eventSender: EventSender = new EventCreator()) {
23 | this.eventSender = eventSender;
24 | }
25 | public async sendAction(action: string): Promise {
26 | await this.eventSender.sendEvent(action);
27 | }
28 | }
29 |
30 | export class Client {
31 | // @ts-ignore
32 | actionCreator: ActionSender;
33 | call() {
34 | this.actionCreator = new ActionCreator();
35 | this.actionCreator.sendAction("Hello");
36 | this.actionCreator = new EventAdapter(new EventCreator());
37 | this.actionCreator.sendAction("Another Action");
38 | }
39 | }
40 |
41 | new Client().call();
42 |
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/Bridge.ts:
--------------------------------------------------------------------------------
1 | interface Box {
2 | id: string;
3 | value: string;
4 | }
5 | interface BoxArranger {
6 | arrangeItem(item: Box, items: Box[]): Box[];
7 | }
8 |
9 | abstract class BoxContainer {
10 | constructor(public items: Box[] = [], protected boxArranger: BoxArranger) {}
11 | arrangeItem(item: Box) {}
12 | }
13 |
14 | class StraightBoxContainer extends BoxContainer {
15 | arrangeItem(item: Box) {
16 | this.items = this.boxArranger.arrangeItem(item, this.items);
17 | }
18 | }
19 |
20 | class ReversingBoxContainer extends BoxContainer {
21 | arrangeItem(item: Box) {
22 | this.items = this.boxArranger.arrangeItem(item, this.items).reverse();
23 | }
24 | }
25 |
26 | class PutLastBoxArranger implements BoxArranger {
27 | arrangeItem(item: Box, items: Box[]): Box[] {
28 | items = items.concat(item);
29 | return items;
30 | }
31 | }
32 |
33 | class PutFirstBoxArranger implements BoxArranger {
34 | arrangeItem(item: Box, items: Box[]): Box[] {
35 | let result = items.slice();
36 | result.unshift(item);
37 | return result;
38 | }
39 | }
40 | const items: Box[] = [
41 | {
42 | id: "1",
43 | value: "abc",
44 | },
45 | ];
46 | const pfa = new PutFirstBoxArranger();
47 | const pla = new PutLastBoxArranger();
48 | const rv = new StraightBoxContainer(items, pla);
49 | rv.arrangeItem({
50 | id: "3",
51 | value: "dfa",
52 | }); // [ { id: '3', value: 'dfa' }, { id: '1', value: 'abc' } ]
53 | console.log(rv.items);
54 | const sc = new StraightBoxContainer(items, pfa);
55 | sc.arrangeItem({
56 | id: "3",
57 | value: "dfa",
58 | });
59 | console.log(sc.items);
60 |
61 | // Implementor type
62 | interface StoreAPI {
63 | store(item: T);
64 | }
65 | // Abstraction type
66 | interface List {
67 | push(item: T): void;
68 | }
69 |
70 | class ArrayList implements List {
71 | constructor(private items: T[], private storeAPI: StoreAPI) {}
72 | push(item: T): void {
73 | this.storeAPI.store(item);
74 | }
75 | // implements methods of List
76 | }
77 | interface ListNode {
78 | data: T;
79 | next: ListNode | null;
80 | }
81 | class LinkedList implements List {
82 | constructor(private root: ListNode, private items: T[]) {}
83 | // implements methods of List
84 | push(item: T): void {
85 | const newNode: ListNode = {data: item, next: null};
86 | newNode.next = this.root;
87 | this.root = newNode;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/Composite.ts:
--------------------------------------------------------------------------------
1 | interface UIElement {
2 | render(): string;
3 | }
4 |
5 | class WindowComposite implements UIElement {
6 | private children: UIElement[];
7 |
8 | constructor() {
9 | this.children = [];
10 | }
11 |
12 | render(): string {
13 | let result = "";
14 | for (let i = 0; i < this.children.length; i += 1) {
15 | result += this.children[i].render();
16 | }
17 | result += "";
18 | return result;
19 | }
20 | addComponent(c: UIElement): void {
21 | this.children.push(c);
22 | }
23 | removeComponent(idx: number): void {
24 | if (this.children.length <= idx) {
25 | throw new Error("index out of bound!");
26 | }
27 | this.children.splice(idx, 1);
28 | }
29 | }
30 |
31 | class Button implements UIElement {
32 | constructor(private text: string) {}
33 | render(): string {
34 | return ``;
35 | }
36 | }
37 | const wc: WindowComposite = new WindowComposite();
38 | wc.addComponent(new Button("Click me"));
39 | wc.addComponent(new Button("No Click me"));
40 | console.info(wc.render()); //
41 |
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/Decorator.test.ts:
--------------------------------------------------------------------------------
1 | import { LogEventDecorator, Event } from "./Decorator";
2 | const spy = jest.spyOn(console, "log").mockImplementation(() => {});
3 |
4 | afterEach(() => {
5 | spy.mockReset();
6 | });
7 |
8 | test("it calls the decorated object method", () => {
9 | const mockSendEvent = jest.fn();
10 | const mock = {
11 | send: mockSendEvent,
12 | };
13 | const log = new LogEventDecorator(mock);
14 | log.send("example");
15 | expect(mockSendEvent).toHaveBeenCalledWith("example");
16 | });
17 |
18 | test("it calls the decorator calls before and after the call to decorated method", () => {
19 | const mockSendEvent = jest.fn();
20 | const mock = {
21 | send: mockSendEvent,
22 | };
23 | const log = new LogEventDecorator(mock);
24 | log.send("example");
25 | expect(spy).toBeCalledTimes(2);
26 | });
27 |
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/Decorator.ts:
--------------------------------------------------------------------------------
1 | export interface Event {
2 | send(message: string): void;
3 | }
4 |
5 | export class SendEmailEvent implements Event {
6 | public send(message: string): void {
7 | // send event using email client
8 | console.log("Currently sending event message", message);
9 | }
10 | }
11 |
12 | export class LogEventDecorator implements Event {
13 | constructor(private event: Event) {
14 | this.event = event;
15 | }
16 |
17 | public send(message: string): void {
18 | console.log("Before sending event message", message);
19 | this.event.send(message); // forward call to event
20 | console.log("After sending event message: ", message);
21 | }
22 | }
23 |
24 | const sendEmail: Event = new SendEmailEvent();
25 | const logSendEmail = new LogEventDecorator(sendEmail);
26 | logSendEmail.send("Hi!");
27 |
28 | function logCall(
29 | target: any,
30 | propertyKey: string,
31 | descriptor: PropertyDescriptor
32 | ) {}
33 |
34 | function LogCall() {
35 | return function (
36 | target: Object,
37 | key: string | symbol,
38 | descriptor: PropertyDescriptor
39 | ) {
40 | const caller = descriptor.value;
41 | descriptor.value = (message: string) => {
42 | console.log("Before sending event message", message);
43 | // @ts-ignore
44 | caller.apply(this, [message]);
45 | console.log("After sending event message", message);
46 | return caller;
47 | };
48 | return descriptor;
49 | };
50 | }
51 |
52 | class EventService {
53 | @LogCall()
54 | createEvent(message: string): void {
55 | console.log("Currently sending event message", message);
56 | }
57 | }
58 |
59 | new EventService().createEvent("Message");
60 |
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/EventCreator.ts:
--------------------------------------------------------------------------------
1 | import {EventSender} from "./Adapter";
2 |
3 | export class EventCreator implements EventSender {
4 | sendEvent(action: string): void {
5 | console.log("Event Created: ", action);
6 | }
7 | }
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/Facade.ts:
--------------------------------------------------------------------------------
1 | class Facade {
2 | constructor(private serviceA: ServiceA, private serviceB: ServiceB) {}
3 |
4 | perform() {
5 | this.serviceA.action();
6 | this.serviceB.action();
7 | // more complex logic here
8 | }
9 | }
10 | interface ServiceA {
11 | action(): void;
12 | }
13 | interface ServiceB {
14 | action(): void;
15 | }
16 |
17 | class ServiceAImpl implements ServiceA {
18 | action(): void {
19 | console.log("Performing action on Service A");
20 | }
21 | }
22 |
23 | class ServiceBImpl implements ServiceB {
24 | action(): void {
25 | console.log("Performing action on Service B");
26 | }
27 | }
28 |
29 | new Facade(new ServiceAImpl(), new ServiceBImpl()).perform();
30 |
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/FacadeExample.ts:
--------------------------------------------------------------------------------
1 | class DocumentService {
2 | create(name: string): Promise {
3 | return Promise.resolve(`Location: /documents/${name}`);
4 | }
5 | }
6 | interface ApiClient {
7 | upload(url: string, blob: Blob): Promise;
8 | }
9 |
10 | class UploadService {
11 | constructor(private client: ApiClient) {}
12 | upload(url: string, blob: Blob): Promise {
13 | return this.client.upload(url, blob);
14 | }
15 | }
16 | class DocumentUploadFacade {
17 | constructor(
18 | private documentService: DocumentService,
19 | private uploadService: UploadService
20 | ) {}
21 |
22 | async createAndUploadDocument(name: string, blob: Blob): Promise {
23 | let path: string | null = null;
24 | let status = false;
25 | try {
26 | path = await this.documentService.create(name);
27 | } catch (e) {
28 | console.error(e);
29 | }
30 | if (path) {
31 | try {
32 | status = await this.uploadService.upload(path, blob);
33 | } catch (e) {
34 | console.error(e);
35 | }
36 | }
37 |
38 | return status;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/chapters/chapter-4_Structural_Design_Patterns/Flyweight.ts:
--------------------------------------------------------------------------------
1 | export interface Flyweight {
2 | perform(customization: { id: string }): void;
3 | }
4 |
5 | export class ConcreteFlyweight implements Flyweight {
6 | constructor(private sharedState: Object) {}
7 |
8 | public perform(customization: { id: string }): void {
9 | console.log(
10 | `Call to ConcreteFlyweight with param: ${customization.id} called`
11 | );
12 | }
13 | }
14 |
15 | export class FlyweightFactory {
16 | private cache = new Map