{"id":479291,"date":"2026-05-11T09:06:55","date_gmt":"2026-05-11T09:06:55","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=479291"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=479291","title":{"rendered":"\u0412\u043e\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435: \u0420\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 TypeScript"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0421\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e TypeScript \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u043d\u0438\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430, \u043d\u043e \u0438 \u0443\u043c\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u0442\u044c \u00ab\u0443\u0437\u043a\u0438\u0435 \u043c\u0435\u0441\u0442\u0430\u00bb \u0432 \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u043c \u043a\u043e\u0434\u0435. \u0417\u0430\u0434\u0430\u0447\u0430 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 &#8212; \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u00ab\u0442\u0443\u0442 \u043e\u0448\u0438\u0431\u043a\u0430\u00bb, \u0430 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0435, \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u044b \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u0445 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430 TypeScript. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c, \u0438 \u0437\u0430\u0434\u0430\u0451\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u044b\u0448\u043b\u0435\u043d\u0438\u0439.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/479\/937\/577\/479937577376c1e76c30ba7c1cc68153.png\" width=\"1000\" height=\"563\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/479\/937\/577\/479937577376c1e76c30ba7c1cc68153.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/479\/937\/577\/479937577376c1e76c30ba7c1cc68153.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<hr\/>\n<h3>\ud83d\udd39 \u0422\u0438\u043f\u044b \u0438 \u0441\u0443\u0436\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u043e\u0434, \u0433\u0434\u0435 TypeScript \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0448\u0438\u0440\u043e\u043a\u0438\u0439 \u0442\u0438\u043f. \u041a\u0430\u043a \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438 \u0437\u0430\u0447\u0435\u043c \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u0411\u044b\u043b\u043e \u274cconst users = new Map(); \/\/ Map&lt;any, any&gt; \u2014 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0448\u0438\u0440\u043e\u043a\u043eusers.set('anna', 28);type Status = 'active' | 'blocked';const [status, setStatus] = useState('active'); \/\/ \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u0430\u043a string<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u0421\u0442\u0430\u043b\u043e \u2705const users = new Map&lt;string, number&gt;(); \/\/ \u0447\u0451\u0442\u043a\u043e: \u043a\u043b\u044e\u0447 \u2014 \u0441\u0442\u0440\u043e\u043a\u0430, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u2014 \u0447\u0438\u0441\u043b\u043eusers.set('anna', 28);type Status = 'active' | 'blocked';const [status, setStatus] = useState&lt;Status&gt;('active'); \/\/ \u0441\u0443\u0436\u0430\u0435\u043c \u0434\u043e \u043d\u0443\u0436\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0417\u0430\u0447\u0435\u043c:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041e\u0448\u0438\u0431\u043a\u0438 \u043b\u043e\u0432\u044f\u0442\u0441\u044f \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438, \u0430 \u043d\u0435 \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0434 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435: \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u043d\u043e, \u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b<\/p>\n<\/li>\n<li>\n<p>\u041b\u0435\u0433\u0447\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c: \u0435\u0441\u043b\u0438 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0442\u0438\u043f &#8212; \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u0432\u0441\u0435 \u043c\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u041d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u0439\u0442\u0435 \u0442\u043e, \u0447\u0442\u043e \u0438 \u0442\u0430\u043a \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041a\u043e\u0433\u0434\u0430 \u0441\u0442\u043e\u0438\u0442 \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u0438\u043f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u0430 \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0432\u0435\u0440\u0438\u0442\u044c\u0441\u044f \u0432\u044b\u0432\u043e\u0434\u0443 \u0442\u0438\u043f\u043e\u0432?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u0418\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e \u274cconst role: string = 'admin'; \/\/ \u0438 \u0442\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e stringconst items = new Map&lt;string, number&gt;([['x', 1]]); \/\/ \u0442\u0438\u043f \u0438 \u0442\u0430\u043a \u0432\u044b\u0432\u0435\u0434\u0435\u0442\u0441\u044fconst [loaded, setLoaded] = useState&lt;boolean&gt;(false); \/\/ boolean \u043e\u0447\u0435\u0432\u0438\u0434\u0435\u043d<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u2705const ROLE = 'admin'; \/\/ \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u0430\u043a 'admin' (\u043b\u0438\u0442\u0435\u0440\u0430\u043b), \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e stringconst items = new Map([['x', 1]]); \/\/ \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f Map&lt;string, number&gt;const [loaded, setLoaded] = useState(false); \/\/ \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f boolean<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u0440\u0430\u0432\u0438\u043b\u043e:<\/strong> \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0439\u0442\u0435 \u0442\u0438\u043f \u044f\u0432\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0441\u0443\u0437\u0438\u0442\u044c \u0442\u0438\u043f. \u0412\u043e \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 &#8212; \u0434\u043e\u0432\u0435\u0440\u044f\u0439\u0442\u0435 TypeScript.  <\/p>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u041d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041a\u0430\u043a \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u041e\u043f\u0430\u0441\u043d\u043e \u274c \u2014 \u043c\u043e\u0436\u043d\u043e \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432const removeFirst = (list: Array&lt;User&gt;) =&gt; {  if (list.length === 0) return list;  return list.splice(1); \/\/ \u043c\u0435\u043d\u044f\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432!};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u2705const removeFirst = (list: ReadonlyArray&lt;User&gt;)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u0430\u0436\u043d\u043e:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041c\u0435\u043d\u044c\u0448\u0435 \u0431\u0430\u0433\u043e\u0432 \u0438\u0437-\u0437\u0430 \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041b\u0435\u0433\u0447\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0438 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u0421\u043b\u043e\u0436\u043d\u043e \u0438 \u043d\u0435\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u274ctype Account = {  id?: number;  email?: string;  isAdmin?: boolean;  permissions?: string[];  plan?: 'free' | 'pro';};\/\/ \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c account?.email?.toLowerCase()...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u0427\u0451\u0442\u043a\u043e \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u2705 \u2014 \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0434\u0438\u0441\u043a\u0440\u0438\u043c\u0438\u043d\u0430\u0442\u043e\u0440\u043e\u043ctype AdminAccount = {  role: 'admin';  id: number;  email: string;  permissions: readonly string[];};type GuestAccount = {  role: 'guest';  tempToken: string;};type Account = AdminAccount | GuestAccount; \/\/ \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0437\u043d\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u0433\u0434\u0435 \u0435\u0441\u0442\u044c<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043b\u044e\u0441\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p>\u042f\u0441\u043d\u043e, \u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0442 \u043b\u0438\u0448\u043d\u0435\u0433\u043e <code>?.<\/code> \u0432 \u043a\u043e\u0434\u0435<\/p>\n<\/li>\n<li>\n<p>\u041e\u0448\u0438\u0431\u043a\u0438 \u00ab\u043f\u043e\u043b\u044f \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442\u00bb \u043b\u043e\u0432\u044f\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u0414\u0438\u0441\u043a\u0440\u0438\u043c\u0438\u043d\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (Discriminated Unions)<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u0427\u0442\u043e \u044d\u0442\u043e \u0438 \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u043e? \u041f\u043e\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430.\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u0411\u044b\u043b\u043e: \u043c\u043d\u043e\u0433\u043e \u0444\u043b\u0430\u0433\u043e\u0432 \u2014 \u0437\u0430\u043f\u0443\u0442\u0430\u043d\u043d\u043e \u274ctype Request = {  isLoading?: boolean;  isError?: boolean;  data?: any;  error?: string;};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u0421\u0442\u0430\u043b\u043e: \u043e\u0434\u0438\u043d \u044f\u0432\u043d\u044b\u0439 \u0441\u0442\u0430\u0442\u0443\u0441 \u2014 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u2705type RequestSuccess = { status: 'success'; data: Product[] };type RequestLoading = { status: 'loading' };type RequestError = { status: 'error'; message: string };type Request = RequestSuccess | RequestLoading | RequestError;\/\/ \u0422\u0435\u043f\u0435\u0440\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442, \u0447\u0442\u043e \u0432\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432\u0441\u0435 \u0441\u043b\u0443\u0447\u0430\u0438:const render = (req: Request) =&gt; {  switch (req.status) {    case 'success': return &lt;List items={req.data} \/&gt;; \/\/ req.data \u0442\u043e\u0447\u043d\u043e \u0435\u0441\u0442\u044c    case 'loading': return &lt;Spinner \/&gt;;    case 'error': return &lt;Error msg={req.message} \/&gt;; \/\/ req.message \u0442\u043e\u0447\u043d\u043e \u0435\u0441\u0442\u044c    \/\/ \u0437\u0430\u0431\u044b\u043b\u0438 \u0441\u043b\u0443\u0447\u0430\u0439? \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u0442!  }};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0417\u0430\u0447\u0435\u043c:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0423\u0431\u0438\u0440\u0430\u0435\u0442 \u043d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0441\u0442\u044c: \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b \u0442\u043e\u0447\u043d\u044b\u0435 \u043f\u043e\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>Exhaustiveness check: \u0435\u0441\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 \u0441\u0442\u0430\u0442\u0443\u0441 &#8212; \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u0435\u0437\u0434\u0435<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0434 \u0441\u0430\u043c\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 as const satisfies &#8212; \u043c\u043e\u0449\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041a\u0430\u043a \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442, \u0447\u0442\u043e\u0431\u044b \u0438 \u0442\u0438\u043f\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u043b\u0438\u0441\u044c, \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">type Role = 'viewer' | 'editor' | 'admin';\/\/ \u274c \u0428\u0438\u0440\u043e\u043a\u0438\u0439 \u0442\u0438\u043fconst ROLES: readonly Role[] = ['viewer', 'editor'];\/\/ \u274c as const \u0431\u0435\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u2014 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445const ROLES = ['viwer', 'edior'] as const; \/\/ \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0438 \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043c!<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u2705 \u0418\u0434\u0435\u0430\u043b\u044c\u043d\u043e: \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u00ab\u0437\u0430\u043c\u043e\u0440\u043e\u0436\u0435\u043d\u044b\u00bb, \u0438 \u0442\u0438\u043f\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u044bconst ROLES = ['viewer', 'editor', 'admin'] as const satisfies readonly Role[];<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0427\u0442\u043e \u0434\u0430\u0451\u0442:<\/strong><\/p>\n<ul>\n<li>\n<p><code>as const<\/code> &#8212; \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f readonly \u0438 \u0441\u0443\u0436\u0430\u0435\u0442 \u0442\u0438\u043f\u044b \u0434\u043e \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><code>satisfies<\/code> &#8212; \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c\u0443 \u0442\u0438\u043f\u0443, \u043d\u043e \u043d\u0435 \u00ab\u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442\u00bb \u0438\u0445<\/p>\n<\/li>\n<li>\n<p>\u0412\u043c\u0435\u0441\u0442\u0435 &#8212; \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u0428\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0442\u0438\u043f\u044b (Template Literal Types)<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041a\u0430\u043a \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u043e\u043f\u0435\u0447\u0430\u0442\u043e\u043a \u0432 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 \u0432\u0440\u043e\u0434\u0435 \u043f\u0443\u0442\u0435\u0439 API \u0438\u043b\u0438 \u043a\u043b\u044e\u0447\u0435\u0439 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u0411\u044b\u043b\u043e \u274c \u2014 \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 = \u043e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435const endpoint = '\/api\/usrers'; \/\/ \"usrers\" \u0432\u043c\u0435\u0441\u0442\u043e \"users\" \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043c\u043e\u043b\u0447\u0438\u0442<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u0421\u0442\u0430\u043b\u043e \u2705 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044ftype ApiPath = 'users' | 'posts' | 'comments';type ApiEndpoint = `\/api\/${ApiPath}`; \/\/ \"\/api\/users\" | \"\/api\/posts\" | \"\/api\/comments\"const endpoint: ApiEndpoint = '\/api\/users'; \/\/ \u2705const bad: ApiEndpoint = '\/api\/usrers'; \/\/ \u274c \u041e\u0448\u0438\u0431\u043a\u0430 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438!<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0413\u0434\u0435 \u0435\u0449\u0451 \u043f\u043e\u043b\u0435\u0437\u043d\u043e:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041a\u043b\u044e\u0447\u0438 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438: <code>translation.${Page}.${Key}<\/code><\/p>\n<\/li>\n<li>\n<p>CSS-\u043a\u043b\u0430\u0441\u0441\u044b: <code>${Color}-${Shade}<\/code> =&gt; <code>'blue-400' | 'red-200'<\/code><\/p>\n<\/li>\n<li>\n<p>SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u044b: <code>SELECT ${Column} FROM ${Table}<\/code><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 any vs unknown<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u0412 \u0447\u0451\u043c \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 <code>any<\/code> &#8212; \u044d\u0442\u043e \u0437\u043b\u043e?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u274c any \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u0438\u043f\u043e\u0432 \u2014 \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u043e\u043b\u0435\u0437\u0443\u0442 \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043dconst data: any = apiCall();const name: string = data.userName; \/\/ \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043c\u043e\u043b\u0447\u0438\u0442, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 userName \u043d\u0435\u0442<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u2705 unknown \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u044f\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043cconst data: unknown = apiCall();\/\/ \u0412\u0430\u0440\u0438\u0430\u043d\u0442 1: \u0442\u0438\u043f-\u0433\u0430\u0440\u0434if (typeof data === 'object' &amp;&amp; data !== null &amp;&amp; 'userName' in data) {  const name = (data as { userName: string }).userName;}\/\/ \u0412\u0430\u0440\u0438\u0430\u043d\u0442 2: \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 (\u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0443\u0432\u0435\u0440\u0435\u043d\u044b!)const name = (data as { userName: string }).userName;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u0440\u0430\u0432\u0438\u043b\u043e:<\/strong> <code>unknown<\/code> &#8212; \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 <code>any<\/code>. \u0412\u0441\u0435\u0433\u0434\u0430 \u0441\u0443\u0436\u0430\u0439\u0442\u0435 \u0442\u0438\u043f \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c.<\/p>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u0423\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432: \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e, \u0430 \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u0442<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>as User<\/code> \u0438\u043b\u0438 <code>user!.name<\/code>?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">type User = { name: string; avatar: string | null };\/\/ \u274c \u041e\u043f\u0430\u0441\u043d\u043e: \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0432\u0435\u0440\u0438\u0442 \u0432\u0430\u043c \u043d\u0430 \u0441\u043b\u043e\u0432\u043e, \u043d\u043e \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u043c\u043e\u0436\u0435\u0442 \u0443\u043f\u0430\u0441\u0442\u044cconst user = { name: 'Misha' } as User; \/\/ avatar \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442!render(user!.avatar); \/\/ Runtime error: cannot read property of null<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u2705 \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e: \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043cif (user.avatar !== null) {  render(user.avatar);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041a\u043e\u0433\u0434\u0430 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0441 \u0447\u0443\u0436\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439, \u0433\u0434\u0435 \u0442\u0438\u043f\u044b \u043d\u0435\u0442\u043e\u0447\u043d\u044b\u0435<\/p>\n<\/li>\n<li>\n<p>\u0422\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u044f\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 (type guard)<\/p>\n<\/li>\n<li>\n<p>\u0421 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u043c, \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 @ts-expect-error vs @ts-ignore<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0433\u043b\u0443\u0448\u0438\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 TypeScript, \u0435\u0441\u043b\u0438 \u0438\u043d\u0430\u0447\u0435 \u043d\u0435\u043b\u044c\u0437\u044f?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u274c @ts-ignore \u2014 \u043e\u0448\u0438\u0431\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u00ab\u0438\u0441\u0447\u0435\u0437\u043d\u0443\u0442\u044c\u00bb \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u0430 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f\/\/ @ts-ignoreconst result = legacyFunc('test');<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u2705 @ts-expect-error \u2014 \u0435\u0441\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0430 \u0443\u0439\u0434\u0451\u0442, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u0442, \u0447\u0442\u043e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043b\u0438\u0448\u043d\u0438\u0439\/\/ @ts-expect-error: legacyFunc \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e, \u0430 \u043d\u0435 \u0441\u0442\u0440\u043e\u043a\u0443 \u2014 \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u043c \u0432 v2const result = legacyFunc('test');<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u0430\u0436\u043d\u043e:<\/strong> <code>@ts-expect-error<\/code> &#8212; \u0441\u0430\u043c\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439\u0441\u044f \u0438 \u0441\u0430\u043c\u043e\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0438\u0439\u0441\u044f. \u041d\u0435 \u0434\u0430\u0451\u0442 \u0437\u0430\u0431\u044b\u0442\u044c \u043f\u0440\u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0434\u043e\u043b\u0433.  <\/p>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 type vs interface<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u0427\u0442\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0438 \u043f\u043e\u0447\u0435\u043c\u0443?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u274c interface \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0432 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432interface Status = 'ok' | 'error'; \/\/ \u041e\u0448\u0438\u0431\u043a\u0430!<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u2705 type \u2014 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0435\u0435type Status = 'ok' | 'error';type User = { name: string; status: Status };<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u0440\u0430\u0432\u0438\u043b\u043e:<\/strong> \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 <code>type<\/code> \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. <code>interface<\/code>&#8212; \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 (declaration merging), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432.<\/p>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u041c\u0430\u0441\u0441\u0438\u0432\u044b: T[] vs Array<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u0415\u0441\u0442\u044c \u043b\u0438 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0438 \u0447\u0442\u043e \u043b\u0443\u0447\u0448\u0435?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u274c \u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 T[] \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0442\u0430\u0442\u044c \u0432 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445const list: readonly string[] = ['a', 'b'];<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u2705 Generic-\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u0443\u0447\u0448\u0435, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0441 readonlyconst list: ReadonlyArray&lt;string&gt; = ['a', 'b'];const matrix: Array&lt;Array&lt;number&gt;&gt; = [[1, 2], [3, 4]];<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043b\u044e\u0441\u044b <\/strong><code><strong>Array&lt;T&gt;<\/strong><\/code><strong>:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041e\u0434\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0439 \u0441\u0442\u0438\u043b\u044c \u0432\u043e \u0432\u0441\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435<\/p>\n<\/li>\n<li>\n<p>\u041b\u0435\u0433\u0447\u0435 \u0447\u0438\u0442\u0430\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0442\u0438\u043f\u044b<\/p>\n<\/li>\n<li>\n<p>\u042f\u0432\u043d\u043e \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432, \u0430 \u043d\u0435 \u0447\u0442\u043e-\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u0435<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u0418\u043c\u043f\u043e\u0440\u0442 \u0442\u0438\u043f\u043e\u0432: import type<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u0417\u0430\u0447\u0435\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0438\u043f\u044b, \u0435\u0441\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e <code>import { X }<\/code>?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u274c \u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u0432 \u0431\u0430\u043d\u0434\u043b \u043b\u0438\u0448\u043d\u0438\u0439 \u043a\u043e\u0434import { User } from '.\/types'; \/\/ User \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f, \u043d\u043e \u0431\u0430\u043d\u0434\u043b\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0444\u0430\u0439\u043b<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u2705 \u0427\u0451\u0442\u043a\u043e: \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f, \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043eimport type { User } from '.\/types';<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0417\u0430\u0447\u0435\u043c:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0423\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0430\u043d\u0434\u043b\u0430 (tree-shaking)<\/p>\n<\/li>\n<li>\n<p>\u042f\u0432\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u0442 \u00ab\u043a\u043e\u0434\u00bb \u0438 \u00ab\u0442\u0438\u043f\u044b\u00bb<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u0424\u0443\u043d\u043a\u0446\u0438\u0438: \u043e\u0434\u0438\u043d \u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u0443\u0447\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u274c \u041d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0437\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438 \u0432 \u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435createOrder('client', false, 60, 120, null, true, 2000);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u2705 \u041e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 \u2014 \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u043c\u0435\u043d\u044f\u0442\u044ccreateOrder({  method: 'client',  validate: false,  minLines: 60,  maxLines: 120,  default: null,  log: true,  timeout: 2000,});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0411\u043e\u043d\u0443\u0441:<\/strong> \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <code>as const satisfies<\/code> \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432.  <\/p>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u0421\u0442\u043e\u0438\u0442 \u043b\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f?\u00bb<\/p>\n<\/blockquote>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>\u041f\u0440\u0430\u0432\u0438\u043b\u043e:<\/strong><\/p>\n<ul>\n<li>\n<p>\u2705 \u0412 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 API, \u0445\u0443\u043a\u0430\u0445, \u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0445 &#8212; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0439\u0442\u0435 \u044f\u0432\u043d\u043e (\u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439)<\/p>\n<\/li>\n<li>\n<p>\u26aa \u0412\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0435 &#8212; \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0432\u0435\u0440\u0438\u0442\u044c\u0441\u044f \u0432\u044b\u0432\u043e\u0434\u0443 \u0442\u0438\u043f\u043e\u0432, \u0435\u0441\u043b\u0438 \u043a\u043e\u0434 \u043f\u0440\u043e\u0441\u0442\u043e\u0439<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"typescript\">\/\/ \u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0445\u0443\u043a \u2014 \u0442\u0438\u043f \u0432\u0430\u0436\u0435\u043dexport const useUsers = (): { users: User[]; loading: boolean } =&gt; { ... }\/\/ \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u2014 \u0432\u044b\u0432\u043e\u0434 \u0442\u0438\u043f\u043e\u0432 \u043e\u043aconst formatName = (user: User) =&gt; `${user.firstName} ${user.lastName}`;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u0424\u043b\u0430\u0433\u0438 boolean vs \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041f\u043e\u0447\u0435\u043c\u0443 \u043b\u0443\u0447\u0448\u0435 \u043e\u0434\u0438\u043d \u0441\u0442\u0430\u0442\u0443\u0441, \u0447\u0435\u043c \u043f\u044f\u0442\u044c \u0431\u0443\u043b\u0435\u0432\u044b\u0445 \u0444\u043b\u0430\u0433\u043e\u0432?\u00bb<\/p>\n<\/blockquote>\n<pre><code class=\"typescript\">\/\/ \u274c \u0424\u043b\u0430\u0433\u0438 \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043d\u0435\u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u044b\u043c\u0438const isPending = true;const isProcessing = false;const isConfirmed = false;\/\/ \u0410 \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 false? \u0410 \u0435\u0441\u043b\u0438 \u0434\u0432\u0430 true \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e?<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u2705 \u041e\u0434\u043d\u043e \u043f\u043e\u043b\u0435 \u2014 \u043e\u0434\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u2014 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0441\u043e\u043c\u043d\u0435\u043d\u0438\u0439type OrderState = 'pending' | 'processing' | 'confirmed' | 'cancelled';const state: OrderState = 'pending';<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0440\u0435\u043d\u0434\u0435\u0440\u044f\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <code>switch<\/code> &#8212; \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442 \u043f\u043e\u043b\u043d\u043e\u0442\u0443<\/p>\n<\/li>\n<li>\n<p>\u041b\u0435\u0433\u0447\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u044b<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 null vs undefined<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u0412 \u0447\u0451\u043c \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0438 \u043a\u043e\u0433\u0434\u0430 \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c?\u00bb<\/p>\n<\/blockquote>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>\u041f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e:<\/strong><\/p>\n<ul>\n<li>\n<p><code>null<\/code> &#8212; \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0435\u0441\u0442\u044c, \u043d\u043e \u043e\u043d\u043e \u00ab\u043f\u0443\u0441\u0442\u043e\u0435\u00bb (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0430\u0432\u0430\u0442\u0430\u0440\u043a\u0430 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430)<\/p>\n<\/li>\n<li>\n<p><code>undefined<\/code> &#8212; \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 (\u043f\u043e\u043b\u0435 \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e, \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e)<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"typescript\">type Profile = {  avatar: string | null; \/\/ \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c, \u043d\u043e \u043f\u043e\u043b\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c  bio?: string; \/\/ \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0417\u0430\u0447\u0435\u043c:<\/strong> \u0427\u0451\u0442\u043a\u0430\u044f \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0430 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u0431\u0430\u0433\u043e\u0432 \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u043e\u0434 \u0441\u0430\u043c\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u043c\u0441\u044f.  <\/p>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u0418\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435: \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043f\u0430\u0441\u0430\u044e\u0442<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041a\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u0442\u0438\u043f\u044b, \u0447\u0442\u043e\u0431\u044b \u043a\u043e\u0434 \u0447\u0438\u0442\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u043a\u043d\u0438\u0433\u0430?\u00bb<\/p>\n<\/blockquote>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"151\" width=\"151\">\n<p align=\"left\">\u0427\u0442\u043e<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0421\u0442\u0438\u043b\u044c<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041f\u0440\u0438\u043c\u0435\u0440<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"151\" width=\"151\">\n<p align=\"left\">\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/p>\n<\/td>\n<td>\n<p align=\"left\">camelCase<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>userList<\/code>, <code>formatPrice<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"151\" width=\"151\">\n<p align=\"left\">\u0411\u0443\u043b\u0435\u0432\u044b<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c <code>is<\/code>\/<code>has<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>isActive<\/code>, <code>hasPermission<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"151\" width=\"151\">\n<p align=\"left\">\u041a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b<\/p>\n<\/td>\n<td>\n<p align=\"left\">UPPER_CASE<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>MAX_RETRIES = 3<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"151\" width=\"151\">\n<p align=\"left\">\u0422\u0438\u043f\u044b, \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b<\/p>\n<\/td>\n<td>\n<p align=\"left\">PascalCase<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>UserProfile<\/code>, <code>ApiResponse<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"151\" width=\"151\">\n<p align=\"left\">\u0414\u0436\u0435\u043d\u0435\u0440\u0438\u043a\u0438<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>T<\/code> + \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>TData<\/code>, <code>TResponse<\/code> (\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e <code>T<\/code>)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"151\" width=\"151\">\n<p align=\"left\">\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b React \/ Vue<\/p>\n<\/td>\n<td>\n<p align=\"left\">PascalCase<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ProductCard<\/code>, <code>CheckoutForm<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"151\" width=\"151\">\n<p align=\"left\">\u041f\u0440\u043e\u043f\u0441\u044b-\u0441\u043e\u0431\u044b\u0442\u0438\u044f<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>on*<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>onSubmit<\/code>, <code>onError<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"151\" width=\"151\">\n<p align=\"left\">\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>handle*<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>handleSubmit<\/code>, <code>handleError<\/code><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p><strong>\u0410\u043a\u0440\u043e\u043d\u0438\u043c\u044b:<\/strong> <code>ApiUrl<\/code>, \u043d\u0435 <code>APIURL<\/code>; <code>FaqList<\/code>, \u043d\u0435 <code>FAQList<\/code>.<\/p>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438: \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0438 \u043d\u0443\u0436\u043d\u044b?<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u0421\u0442\u043e\u0438\u0442 \u043b\u0438 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443?\u00bb<\/p>\n<\/blockquote>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>\u041f\u0440\u0430\u0432\u0438\u043b\u043e:<\/strong><\/p>\n<ul>\n<li>\n<p>\u274c \u041d\u0435 \u043f\u0438\u0448\u0438\u0442\u0435, <em>\u0447\u0442\u043e<\/em> \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u043e\u0434 &#8212; \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u0438\u043c\u0451\u043d \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u2705 \u041f\u0438\u0448\u0438\u0442\u0435, <em>\u043f\u043e\u0447\u0435\u043c\u0443<\/em> \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a &#8212; \u0435\u0441\u043b\u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u043d\u0435\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u0430<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"typescript\">\/\/ \u274c \u0411\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u043e\/\/ \u0423\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u043d\u0430 60, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043c\u0438\u043d\u0443\u0442\u044bconst minutes = seconds * 60;\/\/ \u2705 \u041f\u043e\u043b\u0435\u0437\u043d\u043e\/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e API \u043b\u0438\u043c\u0438\u0442\u0438\u0440\u0443\u0435\u0442 100 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\/\u043c\u0438\u043d\/\/ \u0421\u043c. \u0442\u0438\u043a\u0435\u0442 #4421const data = await fetchWithCache(endpoint);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>TSDoc:<\/strong> \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 API, \u0445\u0443\u043a\u043e\u0432, \u0443\u0442\u0438\u043b\u0438\u0442 &#8212; \u0447\u0442\u043e\u0431\u044b IDE \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0430 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438.  <\/p>\n<\/div>\n<\/details>\n<hr\/>\n<h3>\ud83d\udd39 \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430: \u0433\u0434\u0435 \u0447\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c?<\/h3>\n<h4>\u0412\u043e\u043f\u0440\u043e\u0441:<\/h4>\n<blockquote>\n<p>\u00ab\u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u043d\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0432 \u043a\u0432\u0435\u0441\u0442?\u00bb<\/p>\n<\/blockquote>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code> modules\/ \u2514\u2500\u2500  ProductPage\/     \u251c\u2500\u2500  index.tsx          # \u0422\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430     \u251c\u2500\u2500  components\/        # \u0422\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b     \u2502   \u251c\u2500\u2500 ProductCard\/     \u2502   \u2514\u2500\u2500 PriceBadge\/     \u251c\u2500\u2500  hooks\/             # useProductData, useWishlist     \u251c\u2500\u2500  utils\/             # formatProductPrice     \u2514\u2500\u2500  api\/               # fetchProduct, updateCart<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u0440\u0438\u043d\u0446\u0438\u043f:<\/strong> \u0413\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u043e \u0444\u0438\u0447\u0430\u043c, \u0430 \u043d\u0435 \u043f\u043e \u0442\u0438\u043f\u0430\u043c \u0444\u0430\u0439\u043b\u043e\u0432.  <\/p>\n<p><strong>\u0418\u043c\u043f\u043e\u0440\u0442:<\/strong><\/p>\n<ul>\n<li>\n<p><code>.\/Component<\/code> &#8212; \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0440\u044f\u0434\u043e\u043c<\/p>\n<\/li>\n<li>\n<p><code>@\/modules\/ProductPage\/utils<\/code> &#8212; \u0435\u0441\u043b\u0438 \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u043e\u0447\u0435\u043c\u0443:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0423\u0434\u0430\u043b\u0438\u043b\u0438 \u0444\u0438\u0447\u0443 &#8212; \u0443\u0434\u0430\u043b\u0438\u043b\u0438 \u043f\u0430\u043f\u043a\u0443, \u0438 \u0432\u0441\u0451<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043d\u0435\u0441\u043b\u0438 \u0444\u0438\u0447\u0443 &#8212; \u043d\u0435 \u043d\u0430\u0434\u043e \u043f\u0440\u0430\u0432\u0438\u0442\u044c 20 \u0438\u043c\u043f\u043e\u0440\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041d\u043e\u0432\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442, \u0433\u0434\u0435 \u0447\u0442\u043e<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1033686\/\">https:\/\/habr.com\/ru\/articles\/1033686\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0421\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e TypeScript \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u043d\u0438\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430, \u043d\u043e \u0438 \u0443\u043c\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u0442\u044c \u00ab\u0443\u0437\u043a\u0438\u0435 \u043c\u0435\u0441\u0442\u0430\u00bb \u0432 \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u043c \u043a\u043e\u0434\u0435. \u0417\u0430\u0434\u0430\u0447\u0430 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 &#8212; \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u00ab\u0442\u0443\u0442 \u043e\u0448\u0438\u0431\u043a\u0430\u00bb, \u0430 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0435, \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435.\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u044b \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u0445 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430 TypeScript. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c, \u0438 \u0437\u0430\u0434\u0430\u0451\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u044b\u0448\u043b\u0435\u043d\u0438\u0439.\ud83d\udd39 \u0422\u0438\u043f\u044b \u0438 \u0441\u0443\u0436\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u043e\u0434, \u0433\u0434\u0435 TypeScript \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0448\u0438\u0440\u043e\u043a\u0438\u0439 \u0442\u0438\u043f. \u041a\u0430\u043a \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438 \u0437\u0430\u0447\u0435\u043c \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e?\u00bb\/\/ \u0411\u044b\u043b\u043e \u274cconst users = new Map(); \/\/ Map&lt;any, any&gt; \u2014 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0448\u0438\u0440\u043e\u043a\u043eusers.set(&#8216;anna&#8217;, 28);type Status = &#8216;active&#8217; | &#8216;blocked&#8217;;const [status, setStatus] = useState(&#8216;active&#8217;); \/\/ \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u0430\u043a string\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u0421\u0442\u0430\u043b\u043e \u2705const users = new Map&lt;string, number&gt;(); \/\/ \u0447\u0451\u0442\u043a\u043e: \u043a\u043b\u044e\u0447 \u2014 \u0441\u0442\u0440\u043e\u043a\u0430, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u2014 \u0447\u0438\u0441\u043b\u043eusers.set(&#8216;anna&#8217;, 28);type Status = &#8216;active&#8217; | &#8216;blocked&#8217;;const [status, setStatus] = useState&lt;Status&gt;(&#8216;active&#8217;); \/\/ \u0441\u0443\u0436\u0430\u0435\u043c \u0434\u043e \u043d\u0443\u0436\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439\u0417\u0430\u0447\u0435\u043c:\u041e\u0448\u0438\u0431\u043a\u0438 \u043b\u043e\u0432\u044f\u0442\u0441\u044f \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438, \u0430 \u043d\u0435 \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435\u041a\u043e\u0434 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435: \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u043d\u043e, \u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u041b\u0435\u0433\u0447\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c: \u0435\u0441\u043b\u0438 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0442\u0438\u043f &#8212; \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u0432\u0441\u0435 \u043c\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c\ud83d\udd39 \u041d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u0439\u0442\u0435 \u0442\u043e, \u0447\u0442\u043e \u0438 \u0442\u0430\u043a \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u041a\u043e\u0433\u0434\u0430 \u0441\u0442\u043e\u0438\u0442 \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u0438\u043f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u0430 \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0432\u0435\u0440\u0438\u0442\u044c\u0441\u044f \u0432\u044b\u0432\u043e\u0434\u0443 \u0442\u0438\u043f\u043e\u0432?\u00bb\/\/ \u0418\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e \u274cconst role: string = &#8216;admin&#8217;; \/\/ \u0438 \u0442\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e stringconst items = new Map&lt;string, number&gt;([[&#8216;x&#8217;, 1]]); \/\/ \u0442\u0438\u043f \u0438 \u0442\u0430\u043a \u0432\u044b\u0432\u0435\u0434\u0435\u0442\u0441\u044fconst [loaded, setLoaded] = useState&lt;boolean&gt;(false); \/\/ boolean \u043e\u0447\u0435\u0432\u0438\u0434\u0435\u043d\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u2705const ROLE = &#8216;admin&#8217;; \/\/ \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u0430\u043a &#8216;admin&#8217; (\u043b\u0438\u0442\u0435\u0440\u0430\u043b), \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e stringconst items = new Map([[&#8216;x&#8217;, 1]]); \/\/ \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f Map&lt;string, number&gt;const [loaded, setLoaded] = useState(false); \/\/ \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f boolean\u041f\u0440\u0430\u0432\u0438\u043b\u043e: \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0439\u0442\u0435 \u0442\u0438\u043f \u044f\u0432\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0441\u0443\u0437\u0438\u0442\u044c \u0442\u0438\u043f. \u0412\u043e \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 &#8212; \u0434\u043e\u0432\u0435\u0440\u044f\u0439\u0442\u0435 TypeScript.  \ud83d\udd39 \u041d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u041a\u0430\u043a \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438?\u00bb\/\/ \u041e\u043f\u0430\u0441\u043d\u043e \u274c \u2014 \u043c\u043e\u0436\u043d\u043e \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432const removeFirst = (list: Array&lt;User&gt;) =&gt; {  if (list.length === 0) return list;  return list.splice(1); \/\/ \u043c\u0435\u043d\u044f\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432!};\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u2705const removeFirst = (list: ReadonlyArray&lt;User&gt;)\u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u0430\u0436\u043d\u043e:\u041c\u0435\u043d\u044c\u0448\u0435 \u0431\u0430\u0433\u043e\u0432 \u0438\u0437-\u0437\u0430 \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432\u041b\u0435\u0433\u0447\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c\ud83d\udd39 \u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0438 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438?\u00bb\/\/ \u0421\u043b\u043e\u0436\u043d\u043e \u0438 \u043d\u0435\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u274ctype Account = {  id?: number;  email?: string;  isAdmin?: boolean;  permissions?: string[];  plan?: &#8216;free&#8217; | &#8216;pro&#8217;;};\/\/ \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c account?.email?.toLowerCase()&#8230;\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u0427\u0451\u0442\u043a\u043e \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u2705 \u2014 \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0434\u0438\u0441\u043a\u0440\u0438\u043c\u0438\u043d\u0430\u0442\u043e\u0440\u043e\u043ctype AdminAccount = {  role: &#8216;admin&#8217;;  id: number;  email: string;  permissions: readonly string[];};type GuestAccount = {  role: &#8216;guest&#8217;;  tempToken: string;};type Account = AdminAccount | GuestAccount; \/\/ \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0437\u043d\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u0433\u0434\u0435 \u0435\u0441\u0442\u044c\u041f\u043b\u044e\u0441\u044b:\u042f\u0441\u043d\u043e, \u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438\u041d\u0435\u0442 \u043b\u0438\u0448\u043d\u0435\u0433\u043e ?. \u0432 \u043a\u043e\u0434\u0435\u041e\u0448\u0438\u0431\u043a\u0438 \u00ab\u043f\u043e\u043b\u044f \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442\u00bb \u043b\u043e\u0432\u044f\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443\ud83d\udd39 \u0414\u0438\u0441\u043a\u0440\u0438\u043c\u0438\u043d\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (Discriminated Unions)\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u0427\u0442\u043e \u044d\u0442\u043e \u0438 \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u043e? \u041f\u043e\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430.\u00bb\/\/ \u0411\u044b\u043b\u043e: \u043c\u043d\u043e\u0433\u043e \u0444\u043b\u0430\u0433\u043e\u0432 \u2014 \u0437\u0430\u043f\u0443\u0442\u0430\u043d\u043d\u043e \u274ctype Request = {  isLoading?: boolean;  isError?: boolean;  data?: any;  error?: string;};\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u0421\u0442\u0430\u043b\u043e: \u043e\u0434\u0438\u043d \u044f\u0432\u043d\u044b\u0439 \u0441\u0442\u0430\u0442\u0443\u0441 \u2014 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u2705type RequestSuccess = { status: &#8216;success&#8217;; data: Product[] };type RequestLoading = { status: &#8216;loading&#8217; };type RequestError = { status: &#8216;error&#8217;; message: string };type Request = RequestSuccess | RequestLoading | RequestError;\/\/ \u0422\u0435\u043f\u0435\u0440\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442, \u0447\u0442\u043e \u0432\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432\u0441\u0435 \u0441\u043b\u0443\u0447\u0430\u0438:const render = (req: Request) =&gt; {  switch (req.status) {    case &#8216;success&#8217;: return &lt;List items={req.data} \/&gt;; \/\/ req.data \u0442\u043e\u0447\u043d\u043e \u0435\u0441\u0442\u044c    case &#8216;loading&#8217;: return &lt;Spinner \/&gt;;    case &#8216;error&#8217;: return &lt;Error msg={req.message} \/&gt;; \/\/ req.message \u0442\u043e\u0447\u043d\u043e \u0435\u0441\u0442\u044c    \/\/ \u0437\u0430\u0431\u044b\u043b\u0438 \u0441\u043b\u0443\u0447\u0430\u0439? \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u0442!  }};\u0417\u0430\u0447\u0435\u043c:\u0423\u0431\u0438\u0440\u0430\u0435\u0442 \u043d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0441\u0442\u044c: \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b \u0442\u043e\u0447\u043d\u044b\u0435 \u043f\u043e\u043b\u044fExhaustiveness check: \u0435\u0441\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 \u0441\u0442\u0430\u0442\u0443\u0441 &#8212; \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u0435\u0437\u0434\u0435\u041a\u043e\u0434 \u0441\u0430\u043c\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f\ud83d\udd39 as const satisfies &#8212; \u043c\u043e\u0449\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u041a\u0430\u043a \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442, \u0447\u0442\u043e\u0431\u044b \u0438 \u0442\u0438\u043f\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u043b\u0438\u0441\u044c, \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c?\u00bbtype Role = &#8216;viewer&#8217; | &#8216;editor&#8217; | &#8216;admin&#8217;;\/\/ \u274c \u0428\u0438\u0440\u043e\u043a\u0438\u0439 \u0442\u0438\u043fconst ROLES: readonly Role[] = [&#8216;viewer&#8217;, &#8216;editor&#8217;];\/\/ \u274c as const \u0431\u0435\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u2014 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445const ROLES = [&#8216;viwer&#8217;, &#8216;edior&#8217;] as const; \/\/ \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0438 \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043c!\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u2705 \u0418\u0434\u0435\u0430\u043b\u044c\u043d\u043e: \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u00ab\u0437\u0430\u043c\u043e\u0440\u043e\u0436\u0435\u043d\u044b\u00bb, \u0438 \u0442\u0438\u043f\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u044bconst ROLES = [&#8216;viewer&#8217;, &#8216;editor&#8217;, &#8216;admin&#8217;] as const satisfies readonly Role[];\u0427\u0442\u043e \u0434\u0430\u0451\u0442:as const &#8212; \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f readonly \u0438 \u0441\u0443\u0436\u0430\u0435\u0442 \u0442\u0438\u043f\u044b \u0434\u043e \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u043e\u0432satisfies &#8212; \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c\u0443 \u0442\u0438\u043f\u0443, \u043d\u043e \u043d\u0435 \u00ab\u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442\u00bb \u0438\u0445\u0412\u043c\u0435\u0441\u0442\u0435 &#8212; \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430\ud83d\udd39 \u0428\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0442\u0438\u043f\u044b (Template Literal Types)\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u041a\u0430\u043a \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u043e\u043f\u0435\u0447\u0430\u0442\u043e\u043a \u0432 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 \u0432\u0440\u043e\u0434\u0435 \u043f\u0443\u0442\u0435\u0439 API \u0438\u043b\u0438 \u043a\u043b\u044e\u0447\u0435\u0439 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430?\u00bb\/\/ \u0411\u044b\u043b\u043e \u274c \u2014 \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 = \u043e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435const endpoint = &#8216;\/api\/usrers&#8217;; \/\/ &#171;usrers&#187; \u0432\u043c\u0435\u0441\u0442\u043e &#171;users&#187; \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043c\u043e\u043b\u0447\u0438\u0442\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u0421\u0442\u0430\u043b\u043e \u2705 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044ftype ApiPath = &#8216;users&#8217; | &#8216;posts&#8217; | &#8216;comments&#8217;;type ApiEndpoint = `\/api\/${ApiPath}`; \/\/ &#171;\/api\/users&#187; | &#171;\/api\/posts&#187; | &#171;\/api\/comments&#187;const endpoint: ApiEndpoint = &#8216;\/api\/users&#8217;; \/\/ \u2705const bad: ApiEndpoint = &#8216;\/api\/usrers&#8217;; \/\/ \u274c \u041e\u0448\u0438\u0431\u043a\u0430 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438!\u0413\u0434\u0435 \u0435\u0449\u0451 \u043f\u043e\u043b\u0435\u0437\u043d\u043e:\u041a\u043b\u044e\u0447\u0438 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438: translation.${Page}.${Key}CSS-\u043a\u043b\u0430\u0441\u0441\u044b: ${Color}-${Shade} =&gt; &#8216;blue-400&#8217; | &#8216;red-200&#8217;SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u044b: SELECT ${Column} FROM ${Table}\ud83d\udd39 any vs unknown\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u0412 \u0447\u0451\u043c \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 any &#8212; \u044d\u0442\u043e \u0437\u043b\u043e?\u00bb\/\/ \u274c any \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u0438\u043f\u043e\u0432 \u2014 \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u043e\u043b\u0435\u0437\u0443\u0442 \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043dconst data: any = apiCall();const name: string = data.userName; \/\/ \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043c\u043e\u043b\u0447\u0438\u0442, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 userName \u043d\u0435\u0442\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u2705 unknown \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u044f\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043cconst data: unknown = apiCall();\/\/ \u0412\u0430\u0440\u0438\u0430\u043d\u0442 1: \u0442\u0438\u043f-\u0433\u0430\u0440\u0434if (typeof data === &#8216;object&#8217; &amp;&amp; data !== null &amp;&amp; &#8216;userName&#8217; in data) {  const name = (data as { userName: string }).userName;}\/\/ \u0412\u0430\u0440\u0438\u0430\u043d\u0442 2: \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 (\u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0443\u0432\u0435\u0440\u0435\u043d\u044b!)const name = (data as { userName: string }).userName;\u041f\u0440\u0430\u0432\u0438\u043b\u043e: unknown &#8212; \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 any. \u0412\u0441\u0435\u0433\u0434\u0430 \u0441\u0443\u0436\u0430\u0439\u0442\u0435 \u0442\u0438\u043f \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c.\ud83d\udd39 \u0423\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432: \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e, \u0430 \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u0442\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c as User \u0438\u043b\u0438 user!.name?\u00bbtype User = { name: string; avatar: string | null };\/\/ \u274c \u041e\u043f\u0430\u0441\u043d\u043e: \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0432\u0435\u0440\u0438\u0442 \u0432\u0430\u043c \u043d\u0430 \u0441\u043b\u043e\u0432\u043e, \u043d\u043e \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u043c\u043e\u0436\u0435\u0442 \u0443\u043f\u0430\u0441\u0442\u044cconst user = { name: &#8216;Misha&#8217; } as User; \/\/ avatar \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442!render(user!.avatar); \/\/ Runtime error: cannot read property of null\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u2705 \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e: \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043cif (user.avatar !== null) {  render(user.avatar);}\u041a\u043e\u0433\u0434\u0430 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e:\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0441 \u0447\u0443\u0436\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439, \u0433\u0434\u0435 \u0442\u0438\u043f\u044b \u043d\u0435\u0442\u043e\u0447\u043d\u044b\u0435\u0422\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u044f\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 (type guard)\u0421 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u043c, \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\ud83d\udd39 @ts-expect-error vs @ts-ignore\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0433\u043b\u0443\u0448\u0438\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 TypeScript, \u0435\u0441\u043b\u0438 \u0438\u043d\u0430\u0447\u0435 \u043d\u0435\u043b\u044c\u0437\u044f?\u00bb\/\/ \u274c @ts-ignore \u2014 \u043e\u0448\u0438\u0431\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u00ab\u0438\u0441\u0447\u0435\u0437\u043d\u0443\u0442\u044c\u00bb \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u0430 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f\/\/ @ts-ignoreconst result = legacyFunc(&#8216;test&#8217;);\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u2705 @ts-expect-error \u2014 \u0435\u0441\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0430 \u0443\u0439\u0434\u0451\u0442, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u0442, \u0447\u0442\u043e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043b\u0438\u0448\u043d\u0438\u0439\/\/ @ts-expect-error: legacyFunc \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e, \u0430 \u043d\u0435 \u0441\u0442\u0440\u043e\u043a\u0443 \u2014 \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u043c \u0432 v2const result = legacyFunc(&#8216;test&#8217;);\u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u0430\u0436\u043d\u043e: @ts-expect-error &#8212; \u0441\u0430\u043c\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439\u0441\u044f \u0438 \u0441\u0430\u043c\u043e\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0438\u0439\u0441\u044f. \u041d\u0435 \u0434\u0430\u0451\u0442 \u0437\u0430\u0431\u044b\u0442\u044c \u043f\u0440\u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0434\u043e\u043b\u0433.  \ud83d\udd39 type vs interface\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u0427\u0442\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0438 \u043f\u043e\u0447\u0435\u043c\u0443?\u00bb\/\/ \u274c interface \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0432 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432interface Status = &#8216;ok&#8217; | &#8216;error&#8217;; \/\/ \u041e\u0448\u0438\u0431\u043a\u0430!\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u2705 type \u2014 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0435\u0435type Status = &#8216;ok&#8217; | &#8216;error&#8217;;type User = { name: string; status: Status };\u041f\u0440\u0430\u0432\u0438\u043b\u043e: \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 type \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. interface- \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 (declaration merging), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432.\ud83d\udd39 \u041c\u0430\u0441\u0441\u0438\u0432\u044b: T[] vs Array\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u0415\u0441\u0442\u044c \u043b\u0438 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0438 \u0447\u0442\u043e \u043b\u0443\u0447\u0448\u0435?\u00bb\/\/ \u274c \u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 T[] \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0442\u0430\u0442\u044c \u0432 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445const list: readonly string[] = [&#8216;a&#8217;, &#8216;b&#8217;];\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u2705 Generic-\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u0443\u0447\u0448\u0435, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0441 readonlyconst list: ReadonlyArray&lt;string&gt; = [&#8216;a&#8217;, &#8216;b&#8217;];const matrix: Array&lt;Array&lt;number&gt;&gt; = [[1, 2], [3, 4]];\u041f\u043b\u044e\u0441\u044b Array&lt;T&gt;:\u041e\u0434\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0439 \u0441\u0442\u0438\u043b\u044c \u0432\u043e \u0432\u0441\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435\u041b\u0435\u0433\u0447\u0435 \u0447\u0438\u0442\u0430\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0442\u0438\u043f\u044b\u042f\u0432\u043d\u043e \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432, \u0430 \u043d\u0435 \u0447\u0442\u043e-\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u0435\ud83d\udd39 \u0418\u043c\u043f\u043e\u0440\u0442 \u0442\u0438\u043f\u043e\u0432: import type\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u0417\u0430\u0447\u0435\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0438\u043f\u044b, \u0435\u0441\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e import { X }?\u00bb\/\/ \u274c \u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u0432 \u0431\u0430\u043d\u0434\u043b \u043b\u0438\u0448\u043d\u0438\u0439 \u043a\u043e\u0434import { User } from &#8216;.\/types&#8217;; \/\/ User \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f, \u043d\u043e \u0431\u0430\u043d\u0434\u043b\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u2705 \u0427\u0451\u0442\u043a\u043e: \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f, \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043eimport type { User } from &#8216;.\/types&#8217;;\u0417\u0430\u0447\u0435\u043c:\u0423\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0430\u043d\u0434\u043b\u0430 (tree-shaking)\u042f\u0432\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u0442 \u00ab\u043a\u043e\u0434\u00bb \u0438 \u00ab\u0442\u0438\u043f\u044b\u00bb\u041f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439\ud83d\udd39 \u0424\u0443\u043d\u043a\u0446\u0438\u0438: \u043e\u0434\u0438\u043d \u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u0443\u0447\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u041a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f?\u00bb\/\/ \u274c \u041d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0437\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438 \u0432 \u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435createOrder(&#8216;client&#8217;, false, 60, 120, null, true, 2000);\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\/\/ \u2705 \u041e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 \u2014 \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u043c\u0435\u043d\u044f\u0442\u044ccreateOrder({  method: &#8216;client&#8217;,  validate: false,  minLines: 60,  maxLines: 120,  default: null,  log: true,  timeout: 2000,});\u0411\u043e\u043d\u0443\u0441: \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c as const satisfies \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432.  \ud83d\udd39 \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u0421\u0442\u043e\u0438\u0442 \u043b\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f?\u00bb\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\u041f\u0440\u0430\u0432\u0438\u043b\u043e:\u2705 \u0412 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 API, \u0445\u0443\u043a\u0430\u0445, \u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0445 &#8212; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0439\u0442\u0435 \u044f\u0432\u043d\u043e (\u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439)\u26aa \u0412\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0435 &#8212; \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0432\u0435\u0440\u0438\u0442\u044c\u0441\u044f \u0432\u044b\u0432\u043e\u0434\u0443 \u0442\u0438\u043f\u043e\u0432, \u0435\u0441\u043b\u0438 \u043a\u043e\u0434 \u043f\u0440\u043e\u0441\u0442\u043e\u0439\/\/ \u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0445\u0443\u043a \u2014 \u0442\u0438\u043f \u0432\u0430\u0436\u0435\u043dexport const useUsers = (): { users: User[]; loading: boolean } =&gt; { &#8230; }\/\/ \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u2014 \u0432\u044b\u0432\u043e\u0434 \u0442\u0438\u043f\u043e\u0432 \u043e\u043aconst formatName = (user: User) =&gt; `${user.firstName} ${user.lastName}`;\ud83d\udd39 \u0424\u043b\u0430\u0433\u0438 boolean vs \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432\u0412\u043e\u043f\u0440\u043e\u0441:\u00ab\u041f\u043e\u0447\u0435\u043c\u0443 \u043b\u0443\u0447\u0448\u0435 \u043e\u0434\u0438\u043d \u0441\u0442\u0430\u0442\u0443\u0441, \u0447\u0435\u043c \u043f\u044f\u0442\u044c \u0431\u0443\u043b\u0435\u0432\u044b\u0445 \u0444\u043b\u0430\u0433\u043e\u0432?\u00bb\/\/ \u274c \u0424\u043b\u0430\u0433\u0438 \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043d\u0435\u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u044b\u043c\u0438const&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-479291","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/479291","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=479291"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/479291\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=479291"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=479291"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=479291"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}