Học TypeScript cơ bản cho người mới bắt đầu?

TypeScript (TS) là “JavaScript có thêm kiểu dữ liệu (types)”. Nếu bạn từng bị bug vì truyền nhầm kiểu, đọc code không biết biến đang là gì, hay refactor mà “toang”, thì TypeScript sinh ra để cứu bạn. Bài này sẽ dẫn bạn đi từng bước: cài đặt, chạy được chương trình TS đầu tiên, hiểu các kiểu dữ liệu cốt lõi, và áp dụng TS vào dự án thực tế (Node.js hoặc Frontend).

{"type":"doc","content":[{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"I. TypeScript là gì và vì sao nên học?"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. TypeScript giải quyết vấn đề gì?"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"TypeScript bổ sung:"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"Static typing"},{"type":"text","text":": kiểm tra kiểu ngay lúc viết code (compile-time)."}]}]},{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"Tự động gợi ý tốt hơn"},{"type":"text","text":" (IntelliSense): IDE hiểu code sâu hơn."}]}]},{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"Refactor an toàn"},{"type":"text","text":": đổi tên, tách hàm, chỉnh cấu trúc mà ít rủi ro."}]}]},{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"Code dễ đọc hơn"},{"type":"text","text":": “hợp đồng” kiểu dữ liệu rõ ràng."}]}]}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. TypeScript có thay thế JavaScript không?"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Không. TypeScript "},{"type":"text","marks":[{"type":"bold"}],"text":"biên dịch (compile)"},{"type":"text","text":" về JavaScript để chạy trên Node.js / trình duyệt. Bạn vẫn cần hiểu JS cơ bản (biến, function, object, async/await…)."}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"II. Chuẩn bị môi trường và chạy chương trình TypeScript đầu tiên"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Cài Node.js và TypeScript"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Bạn cần Node.js (kèm npm). Sau đó cài TypeScript:"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"npm init -y\nnpm install -D typescript\nnpx tsc --version\n"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Cài thêm "},{"type":"text","marks":[{"type":"code"}],"text":"ts-node"},{"type":"text","text":" để chạy TS trực tiếp (tiện cho học tập):"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"npm install -D ts-node @types/node\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. Tạo "},{"type":"text","marks":[{"type":"code"}],"text":"tsconfig.json"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"code"}],"text":"tsconfig.json"},{"type":"text","text":" là file cấu hình compiler."}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"npx tsc --init\n"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Gợi ý cấu hình “dễ chịu cho người mới” (bạn có thể chỉnh lại sau):"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"{\n \"compilerOptions\": {\n \"target\": \"ES2020\",\n \"module\": \"CommonJS\",\n \"outDir\": \"dist\",\n \"rootDir\": \"src\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true\n }\n}\n"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Tạo cấu trúc thư mục:"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"mkdir src\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"3. Viết và chạy “Hello TypeScript”"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Tạo "},{"type":"text","marks":[{"type":"code"}],"text":"src/index.ts"},{"type":"text","text":":"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"const message: string = \"Hello TypeScript!\";\nconsole.log(message);\n"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Chạy bằng "},{"type":"text","marks":[{"type":"code"}],"text":"ts-node"},{"type":"text","text":":"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"npx ts-node src/index.ts\n"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Hoặc compile sang JS rồi chạy:"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"npx tsc\nnode dist/index.js\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"III. Nắm vững các kiểu dữ liệu cơ bản (Types cơ bản)"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Kiểu nguyên thủy: "},{"type":"text","marks":[{"type":"code"}],"text":"string"},{"type":"text","text":", "},{"type":"text","marks":[{"type":"code"}],"text":"number"},{"type":"text","text":", "},{"type":"text","marks":[{"type":"code"}],"text":"boolean"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"let name: string = \"An\";\nlet age: number = 20;\nlet isStudent: boolean = true;\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. Mảng và tuple"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"const scores: number[] = [10, 9, 8];\nconst tags: Array<string> = [\"ts\", \"js\"];\n\nconst userTuple: [string, number] = [\"Alice\", 30];\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"3. "},{"type":"text","marks":[{"type":"code"}],"text":"any"},{"type":"text","text":" và vì sao nên tránh"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"code"}],"text":"any"},{"type":"text","text":" tắt kiểm tra kiểu (giống JS “thuần”), dễ gây bug."}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"let data: any = 123;\ndata = \"abc\";\ndata.notExist(); // IDE/TS không chặn\n"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Thay bằng "},{"type":"text","marks":[{"type":"code"}],"text":"unknown"},{"type":"text","text":" để an toàn hơn:"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"let value: unknown = \"hello\";\n\nif (typeof value === \"string\") {\n console.log(value.toUpperCase());\n}\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"4. "},{"type":"text","marks":[{"type":"code"}],"text":"null"},{"type":"text","text":", "},{"type":"text","marks":[{"type":"code"}],"text":"undefined"},{"type":"text","text":" và Strict mode"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Với "},{"type":"text","marks":[{"type":"code"}],"text":"\"strict\": true"},{"type":"text","text":", TS bắt bạn xử lý trường hợp "},{"type":"text","marks":[{"type":"code"}],"text":"undefined/null"},{"type":"text","text":"."}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"function printLength(s?: string) {\n if (!s) return;\n console.log(s.length);\n}\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"IV. Kiểu nâng cao “đáng tiền”: Union, Literal, Type Alias"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Union types: “hoặc cái này hoặc cái kia”"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"type Id = string | number;\n\nfunction printId(id: Id) {\n console.log(\"ID:\", id);\n}\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. Narrowing: “thu hẹp kiểu” bằng "},{"type":"text","marks":[{"type":"code"}],"text":"typeof"},{"type":"text","text":" / "},{"type":"text","marks":[{"type":"code"}],"text":"in"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"function format(input: string | number) {\n if (typeof input === \"number\") {\n return input.toFixed(2);\n }\n return input.trim();\n}\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"3. Literal types: giới hạn giá trị hợp lệ"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"type Role = \"admin\" | \"user\" | \"guest\";\n\nfunction setRole(role: Role) {\n console.log(\"Role:\", role);\n}\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"V. Object typing: Interface vs Type"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Khai báo object bằng "},{"type":"text","marks":[{"type":"code"}],"text":"interface"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"interface User {\n id: number;\n name: string;\n email?: string; // optional\n}\n\nconst u1: User = { id: 1, name: \"An\" };\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. Dùng "},{"type":"text","marks":[{"type":"code"}],"text":"type"},{"type":"text","text":" cho object và union"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"type Product = {\n id: string;\n price: number;\n};\n\ntype ApiResult<T> =\n | { ok: true; data: T }\n | { ok: false; error: string };\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"3. 1.1 Khi nào dùng "},{"type":"text","marks":[{"type":"code"}],"text":"interface"},{"type":"text","text":"?"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Thường dùng cho "},{"type":"text","marks":[{"type":"bold"}],"text":"shape của object"},{"type":"text","text":", dễ mở rộng (declaration merging)."}]}]},{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Hay gặp trong framework (React props, library types)."}]}]}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"4. 1.2 Khi nào dùng "},{"type":"text","marks":[{"type":"code"}],"text":"type"},{"type":"text","text":"?"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Khi cần "},{"type":"text","marks":[{"type":"bold"}],"text":"union / intersection"},{"type":"text","text":" ("},{"type":"text","marks":[{"type":"code"}],"text":"|"},{"type":"text","text":", "},{"type":"text","marks":[{"type":"code"}],"text":"&"},{"type":"text","text":"), literal phức tạp."}]}]},{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Tạo các kiểu tiện ích, mapping types."}]}]}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"VI. Function trong TypeScript: Tham số, return type, overload"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Kiểu tham số và kiểu trả về"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"function add(a: number, b: number): number {\n return a + b;\n}\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. Optional và default parameter"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"function greet(name: string = \"bạn\"): string {\n return `Xin chào ${name}`;\n}\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"3. Function type"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"type Mapper = (x: number) => string;\n\nconst toStr: Mapper = (x) => `#${x}`;\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"VII. Generics: Viết code “tái sử dụng” mà vẫn an toàn kiểu"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Generic function"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"function identity<T>(value: T): T {\n return value;\n}\n\nconst a = identity<number>(10);\nconst b = identity(\"hello\"); // TS tự suy luận T = string\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. Generic với mảng"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"function first<T>(arr: T[]): T | undefined {\n return arr[0];\n}\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"3. 1.1 Generic type cho API response"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"type ApiResponse<T> = {\n data: T;\n meta: { requestId: string };\n};\n\ntype UserDTO = { id: number; name: string };\n\nconst res: ApiResponse<UserDTO> = {\n data: { id: 1, name: \"An\" },\n meta: { requestId: \"abc\" }\n};\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"VIII. Enum, nhưng đừng lạm dụng"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Dùng "},{"type":"text","marks":[{"type":"code"}],"text":"enum"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"enum Status {\n Idle = \"IDLE\",\n Loading = \"LOADING\",\n Success = \"SUCCESS\",\n Error = \"ERROR\"\n}\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. 1.1 Thay thế enum bằng literal union (thường gọn hơn)"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"type Status2 = \"IDLE\" | \"LOADING\" | \"SUCCESS\" | \"ERROR\";\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"IX. Class và OOP cơ bản (nếu bạn cần)"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Class với access modifiers"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"class BankAccount {\n private balance: number;\n\n constructor(initial: number) {\n this.balance = initial;\n }\n\n deposit(amount: number) {\n this.balance += amount;\n }\n\n getBalance() {\n return this.balance;\n }\n}\n\nconst acc = new BankAccount(100);\nacc.deposit(50);\nconsole.log(acc.getBalance());\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"X. Dự án mini: Xây “Todo Service” bằng TypeScript (Node.js)"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Tạo model và service"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"code"}],"text":"src/todo.ts"},{"type":"text","text":":"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"export type Todo = {\n id: string;\n title: string;\n done: boolean;\n};\n\nexport class TodoService {\n private todos: Todo[] = [];\n\n add(title: string): Todo {\n const todo: Todo = { id: crypto.randomUUID(), title, done: false };\n this.todos.push(todo);\n return todo;\n }\n\n toggle(id: string): Todo | undefined {\n const t = this.todos.find(x => x.id === id);\n if (!t) return undefined;\n t.done = !t.done;\n return t;\n }\n\n list(): Todo[] {\n return [...this.todos];\n }\n}\n"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"code"}],"text":"src/index.ts"},{"type":"text","text":":"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"import { TodoService } from \"./todo\";\n\nconst service = new TodoService();\n\nconst t1 = service.add(\"Học TypeScript\");\nconst t2 = service.add(\"Viết mini project\");\n\nservice.toggle(t1.id);\n\nconsole.log(service.list());\n"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Chạy:"}]},{"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"npx ts-node src/index.ts\n"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. 1.1 Lưu ý về "},{"type":"text","marks":[{"type":"code"}],"text":"crypto.randomUUID()"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Node.js hiện đại hỗ trợ "},{"type":"text","marks":[{"type":"code"}],"text":"crypto.randomUUID()"},{"type":"text","text":"."}]}]},{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Nếu bạn gặp lỗi “crypto is not defined”, hãy đảm bảo môi trường Node đủ mới hoặc import đúng kiểu."}]}]}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"XI. Checklist “cần nhớ” khi mới học TypeScript"}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"1. Đừng lạm dụng type"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"TypeScript giúp bạn an toàn hơn, nhưng type quá phức tạp sẽ phản tác dụng."}]}]},{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Ưu tiên "},{"type":"text","marks":[{"type":"bold"}],"text":"đơn giản, rõ ràng"},{"type":"text","text":", rồi mới tối ưu dần."}]}]}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"2. Tránh "},{"type":"text","marks":[{"type":"code"}],"text":"any"},{"type":"text","text":", ưu tiên "},{"type":"text","marks":[{"type":"code"}],"text":"unknown"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"code"}],"text":"any"},{"type":"text","text":" là “đường tắt” nhưng dễ trượt chân."}]}]},{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"code"}],"text":"unknown"},{"type":"text","text":" bắt bạn kiểm tra kiểu trước khi dùng."}]}]}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"3. Luôn bật "},{"type":"text","marks":[{"type":"code"}],"text":"strict"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Ban đầu hơi khó chịu, nhưng về lâu dài cực đáng."}]}]}]},{"type":"heading","attrs":{"textAlign":null,"level":3},"content":[{"type":"text","text":"4. Dùng TS như “người review code”"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Khi TS báo lỗi, đừng tắt đi vội. Hãy hiểu vì sao nó báo."}]}]}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"XII. Kết luận"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","text":"Nếu bạn mới bắt đầu, mục tiêu trong 1–2 tuần đầu là: "},{"type":"text","marks":[{"type":"bold"}],"text":"chạy được TS, hiểu các type cơ bản, union/narrowing, interface/type, generics căn bản"},{"type":"text","text":", và viết được một mini project nhỏ. Khi đã quen, bạn sẽ thấy TypeScript giúp code “đỡ mệt”, ít bug hơn, và dễ mở rộng hơn rất nhiều."}]},{"type":"heading","attrs":{"textAlign":null,"level":2},"content":[{"type":"text","text":"Tài liệu tham khảo"}]},{"type":"paragraph","attrs":{"textAlign":null},"content":[{"type":"text","marks":[{"type":"link","attrs":{"href":"https://www.typescriptlang.org/docs/","target":"_blank","rel":"noopener noreferrer nofollow","class":null}}],"text":"https://www.typescriptlang.org/docs/"},{"type":"hardBreak"},{"type":"text","marks":[{"type":"link","attrs":{"href":"https://www.typescriptlang.org/tsconfig/","target":"_blank","rel":"noopener noreferrer nofollow","class":null}}],"text":"https://www.typescriptlang.org/tsconfig/"},{"type":"hardBreak"},{"type":"text","marks":[{"type":"link","attrs":{"href":"https://www.typescriptlang.org/play","target":"_blank","rel":"noopener noreferrer nofollow","class":null}}],"text":"https://www.typescriptlang.org/play"},{"type":"hardBreak"},{"type":"text","marks":[{"type":"link","attrs":{"href":"https://github.com/microsoft/TypeScript","target":"_blank","rel":"noopener noreferrer nofollow","class":null}}],"text":"https://github.com/microsoft/TypeScript"}]}]}