{"id":302742,"date":"2020-04-29T15:00:56","date_gmt":"2020-04-29T15:00:56","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=302742"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=302742","title":{"rendered":"\u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 TypeScript"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/oleg-bunin\/blog\/499634\/\">\u0424\u0440\u0438\u0434\u0430\u0439\u0432\u0438\u043d\u0433 \u2014 \u043d\u044b\u0440\u044f\u043d\u0438\u0435 \u043d\u0430 \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u0431\u0435\u0437 \u0430\u043a\u0432\u0430\u043b\u0430\u043d\u0433\u0430. \u041d\u044b\u0440\u044f\u043b\u044c\u0449\u0438\u043a \u043e\u0449\u0443\u0449\u0430\u0435\u0442 \u043d\u0430 \u0441\u0435\u0431\u0435 \u0437\u0430\u043a\u043e\u043d \u0410\u0440\u0445\u0438\u043c\u0435\u0434\u0430: \u043e\u043d \u0432\u044b\u0442\u0435\u0441\u043d\u044f\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u044a\u0451\u043c \u0432\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0442\u043d\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u044b\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u0440\u043e\u0432 \u0434\u0430\u044e\u0442\u0441\u044f \u0442\u044f\u0436\u0435\u043b\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u043d\u043e \u043f\u043e\u0442\u043e\u043c \u0441\u0438\u043b\u0430 \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u043b\u0449\u0438 \u0432\u043e\u0434\u044b \u043d\u0430\u0434 \u0442\u043e\u0431\u043e\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c \u0434\u0432\u0438\u0433\u0430\u0442\u044c\u0441\u044f \u0433\u043b\u0443\u0431\u0436\u0435. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0442\u0438\u043f\u043e\u0432 TypeScript \u2014 \u043f\u043e \u043c\u0435\u0440\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043b\u0435\u0433\u0447\u0435. \u041d\u043e \u043d\u0430\u0434\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u0432\u043e\u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043d\u044b\u0440\u043d\u0443\u0442\u044c.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/sh\/eb\/y9\/sheby96u0qt6o3usirdpsc78hpg.jpeg\"><br \/>  <font color=\"gray\"><i>\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f \u0441 \u0441\u0430\u0439\u0442\u0430 <a href=\"https:\/\/www.oneoceanonebreath.com\/freediving-photography\">One Ocean One Breath<\/a>.<\/i><\/font><\/p>\n<p>  <strong>\u041c\u0438\u0445\u0430\u0438\u043b \u0411\u0430\u0448\u0443\u0440\u043e\u0432<\/strong> (<a href=\"https:\/\/habr.com\/ru\/users\/saitonakamura\/\" class=\"user_link\">saitonakamura<\/a>) \u2014 Senior Frontend Engineer \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 WiseBits, \u0444\u0430\u043d\u0430\u0442 TypeScript \u0438 \u0444\u0440\u0438\u0434\u0430\u0439\u0432\u0435\u0440-\u043b\u044e\u0431\u0438\u0442\u0435\u043b\u044c. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f TypeScript \u0438 \u043d\u044b\u0440\u044f\u043d\u0438\u044f \u043d\u0430 \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u043d\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b. \u041c\u0438\u0445\u0430\u0438\u043b \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 discriminated unions, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0432\u043e\u0434 \u0442\u0438\u043f\u043e\u0432, \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u0430 \u043d\u043e\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0438 \u0431\u0440\u0435\u043d\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. \u0417\u0430\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u0434\u044b\u0445\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0439\u0442\u0435\u0441\u044c.<a name=\"habracut\"><\/a><\/p>\n<div class=\"oembed\">\n<div>\n<div style=\"left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;\"><iframe src=\"https:\/\/www.youtube.com\/embed\/m0uRxCCno00?rel=0&amp;showinfo=1&amp;hl=en-US\" style=\"border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;\" allowfullscreen scrolling=\"no\" allow=\"encrypted-media; accelerometer; gyroscope; picture-in-picture\"><\/iframe><\/div>\n<\/div>\n<\/div>\n<p><font color=\"gray\"><i>\u041f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 GitHub \u0441 \u043a\u043e\u0434\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 <a href=\"https:\/\/saitonakamura.github.io\/freediving-into-typescript\/\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/i><\/font><\/p>\n<h2>\u0422\u0438\u043f \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f<\/h2>\n<p>  \u0422\u0438\u043f\u044b \u0441\u0443\u043c\u043c\u044b \u0437\u0432\u0443\u0447\u0438\u0442 \u0430\u043b\u0433\u0435\u0431\u0440\u0430\u0438\u0447\u043d\u043e \u2014 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435. \u0412 ReasonML \u043e\u043d\u0438 \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f variant, \u0432 Haskell \u2014 tagged union, \u0430 \u0432 F# \u0438 \u0432 TypeScript \u2014 discriminated union.<\/p>\n<p>  \u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u044f \u0434\u0430\u0451\u0442 \u0442\u0430\u043a\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435: \u00ab\u0422\u0438\u043f \u0441\u0443\u043c\u043c\u044b \u2014 \u044d\u0442\u043e \u0441\u0443\u043c\u043c\u0430 \u0442\u0438\u043f\u043e\u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439\u00bb.<br \/>  <em> \u2014 \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u043a\u0430\u043f\u0438\u0442\u0430\u043d!<\/em><\/p>\n<p>  \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u043d\u0435\u043b\u044c\u0437\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e, \u043d\u043e \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f. \u041f\u043e\u0439\u0434\u0435\u043c \u043e\u0442 \u0447\u0430\u0441\u0442\u043d\u043e\u0433\u043e \u0438 \u043d\u0430\u0447\u043d\u0451\u043c \u0441 \u0442\u0438\u043f\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0442\u0438\u043f <code>Task<\/code>. \u0423 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u043f\u043e\u043b\u044f: <code>id<\/code> \u0438 \u043a\u0442\u043e \u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043b.<\/p>\n<pre><code class=\"javascript\">type Task = { id: number, whoCreated: number }<\/code><\/pre>\n<p>  \u042d\u0442\u043e \u0442\u0438\u043f \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u2014 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u0438\u043b\u0438<strong> intersection<\/strong>. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u043e\u0442 \u0436\u0435 \u043a\u043e\u0434, \u043a\u0430\u043a \u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u043e\u043b\u0435 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<pre><code class=\"javascript\">type Task = { id: number } &amp; { whoCreated: number }<\/code><\/pre>\n<p>  \u0412 \u0430\u043b\u0433\u0435\u0431\u0440\u0435 \u0432\u044b\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043d\u0438\u0439 \u044d\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435\u043c: \u044d\u0442\u043e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u00ab\u0418\u00bb \u0438\u043b\u0438 \u00abAND\u00bb. \u0422\u0438\u043f \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u2014 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0434\u0432\u0443\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.  <\/p>\n<blockquote><p>\u041e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435.<\/p><\/blockquote>\n<p>\u0422\u0438\u043f \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d \u043f\u043e\u043b\u044f\u043c\u0438. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u043b\u044e\u0431\u0438\u043c Prototype \u0438 \u0440\u0435\u0448\u0438\u043b\u0438, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 <code>leftPad<\/code>.<\/p>\n<pre><code class=\"javascript\">type RichString = string &amp; { leftPad: (toLength: number) =&gt; string }<\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0433\u043e \u0432 <code>String.prototype<\/code>. \u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0432 \u0442\u0438\u043f\u0430\u0445, \u0432\u043e\u0437\u044c\u043c\u0451\u043c string \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u041c\u0435\u0442\u043e\u0434 \u0438 string \u2014 \u044d\u0442\u043e \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435.<\/p>\n<h2>\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435<\/h2>\n<p>  \u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u2014 <strong>union<\/strong> \u2014 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u0434\u0430\u0451\u0442 \u0448\u0438\u0440\u0438\u043d\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0432 CSS: \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 10 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0438\u043b\u0438 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f CSS \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0430\u043a.<\/p>\n<pre><code class=\"javascript\">type Width = string | number<\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u043b\u043e\u0436\u043d\u0435\u0435. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0430. \u041e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0442\u0440\u0435\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u0445: \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0430, \u043f\u0440\u0438\u043d\u044f\u0442\u0430 \u0432 \u0440\u0430\u0431\u043e\u0442\u0443 \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430.<\/p>\n<pre><code class=\"javascript\">type InitialTask = { id: number, whoCreated: number } type InWorkTask = { id: number, whoCreated: number } type FinishTask = { id: number, whoCreated: number, finishDate: Date }  type Task = InitialTask | InWorkTask | FinishedTask<\/code><\/pre>\n<p>  \u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u0438 \u0432\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u0445 \u0443 \u0437\u0430\u0434\u0430\u0447\u0438 \u0435\u0441\u0442\u044c <code>id<\/code> \u0438 \u043a\u0442\u043e \u0435\u0451 \u0441\u043e\u0437\u0434\u0430\u043b, \u0430 \u0432 \u0442\u0440\u0435\u0442\u044c\u0435\u043c \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0430\u0442\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f. \u0422\u0443\u0442 \u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u2014 \u043b\u0438\u0431\u043e \u0442\u043e, \u043b\u0438\u0431\u043e \u044d\u0442\u043e.<\/p>\n<p>  <strong><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em><\/strong><em>. \u0412\u043c\u0435\u0441\u0442\u043e <\/em><code>type<\/code><em> \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <\/em><code>interface<\/code><em>. \u041d\u043e \u0435\u0441\u0442\u044c \u043d\u044e\u0430\u043d\u0441\u044b. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 union \u0438 intersection \u2014 \u044d\u0442\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u0442\u0438\u043f. \u041c\u043e\u0436\u043d\u043e \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c intersection \u0447\u0435\u0440\u0435\u0437 <\/em><code>extends<\/code><em>, \u043d\u043e union \u0447\u0435\u0440\u0435\u0437 <\/em><code>interface<\/code><em> \u043d\u0435\u043b\u044c\u0437\u044f. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c <\/em><code>type<\/code><em> \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u043e\u0440\u043e\u0447\u0435.<\/p>\n<p>  <\/em><code>interface<\/code><em> \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0441\u043b\u0438\u044f\u043d\u0438\u044f \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0446\u0438\u0439. \u0422\u0438\u043f\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0440\u0430\u0436\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <\/em><code>interface<\/code><em>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0434\u0440\u0443\u0433\u0438\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0435\u0433\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438. \u0422\u0430\u043a \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, JQuery-\u043f\u043b\u0430\u0433\u0438\u043d\u044b.<\/em><\/p>\n<h2>\u0421\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0442\u0438\u043f\u043e\u0432<\/h2>\n<p>  \u041d\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u2014 \u0432 TypeScript <strong>\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u0430\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0442\u0438\u043f\u043e\u0432<\/strong>. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0443 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0438 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043f\u043e\u043b\u0435\u0439, \u0442\u043e \u044d\u0442\u043e \u0434\u0432\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u0442\u0438\u043f\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c 10 \u0442\u0438\u043f\u043e\u0432 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f\u043c\u0438, \u043d\u043e \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 (\u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438). \u0415\u0441\u043b\u0438 \u043f\u043e\u0434\u0430\u0434\u0438\u043c \u043b\u044e\u0431\u043e\u0439 \u0438\u0437 10 \u0442\u0438\u043f\u043e\u0432 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0438\u0445, TypeScript \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0440\u0430\u0436\u0430\u0442\u044c.<\/p>\n<p>  \u0412 Java \u0438\u043b\u0438 C# \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442 <strong>\u043d\u043e\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438<\/strong>. \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0435 \u0436\u0435 10 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0438\u0445. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u0442 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435 \u043f\u0440\u044f\u043c\u044b\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438 \u0442\u0438\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<p>  \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u043e\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0432 \u043f\u043e\u043b\u0435: <code>enum<\/code> \u0438\u043b\u0438 <code>string<\/code>. \u041d\u043e \u0442\u0438\u043f\u044b \u0441\u0443\u043c\u043c\u044b \u044d\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u043a\u043e\u0434 \u0431\u043e\u043b\u0435\u0435 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u043d\u043e, \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0442\u0435\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>  \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a ReasonML. \u0412\u043e\u0442 \u043a\u0430\u043a \u044d\u0442\u043e\u0442 \u0442\u0438\u043f \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043c.<\/p>\n<pre><code class=\"javascript\">type Task = | Initial({ id: int, whoCreated: int }) | InWork({ id: int, whoCreated: int }) | Finished({         id: int,         whoCreated: int,         finshDate: Date     })<\/code><\/pre>\n<p>  \u0422\u0435 \u0436\u0435 \u043f\u043e\u043b\u044f, \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e <code>int<\/code> \u0432\u043c\u0435\u0441\u0442\u043e <code>number<\/code>. \u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u0433\u043b\u044f\u0434\u0435\u0442\u044c\u0441\u044f, \u0437\u0430\u043c\u0435\u0442\u0438\u043c <code>Initial<\/code>, <code>InWork<\/code> \u0438 <code>Finished<\/code>. \u041e\u043d\u0438 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u0441\u043b\u0435\u0432\u0430, \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u0442\u0438\u043f\u0430, \u0430 \u0441\u043f\u0440\u0430\u0432\u0430 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438. \u042d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u0447\u043a\u0430 \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438, \u0430 \u0447\u0430\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043b\u0438\u0447\u0438\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u043e\u0442 \u0432\u0442\u043e\u0440\u043e\u0433\u043e.<\/p>\n<p>  <strong>\u041b\u0430\u0439\u0444\u0445\u0430\u043a<\/strong>. \u0414\u043b\u044f \u043e\u0431\u0449\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u0430\u0448\u0438 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438) \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0444\u0430\u0439\u043b <code>global.d.ts<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u043d\u0435\u0433\u043e \u0432\u0441\u0435 \u0442\u0438\u043f\u044b. \u041e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0438\u0434\u043d\u044b \u043f\u043e \u0432\u0441\u0435\u0439 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u0435 TypeScript \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u044f\u0432\u043d\u043e\u0433\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0430. \u042d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435 \u043d\u0430\u0434\u043e \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0438\u0442\u044c\u0441\u044f \u043e \u0442\u043e\u043c, \u0433\u0434\u0435 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0442\u0438\u043f\u044b.<\/p>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u043e\u0433\u043e Redux-\u043a\u043e\u0434\u0430.<\/p>\n<pre><code class=\"javascript\">export const taskReducer = (state, action) = &gt; {     switch (action.type) {         case &quot;TASK_FETCH&quot;:             return { isFetching: true }         case &quot;TASK_SUCCESS&quot;:             return { isFetching: false, task: action.payload }         case &quot;TASK_FAIL&quot;:             return { isFetching: false, erro: action.payload }     }          return state }<\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u043a\u043e\u0434 \u043d\u0430 TypeScript. \u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u2014 \u0438\u0437 <code>.js<\/code> \u0432 <code>.ts<\/code>. \u0412\u043a\u043b\u044e\u0447\u0438\u043c \u0432\u0441\u0435 state-\u043e\u043f\u0446\u0438\u0438 \u0438 \u043e\u043f\u0446\u0438\u044e noImplicitAny. \u042d\u0442\u0430 \u043e\u043f\u0446\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d \u0442\u0438\u043f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>  \u0422\u0438\u043f\u0438\u0437\u0438\u0440\u0443\u0435\u043c <code>State<\/code>: \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u043b\u0435 <code>isFetching<\/code>, <code>Task<\/code> (\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0431\u044b\u0442\u044c) \u0438 <code>Error<\/code>.<\/p>\n<pre><code class=\"javascript\">type Task = { title: string }  declare module &quot;*.jpg&quot; {     const url: string     export default url }  declare module &quot;*.png&quot; {     const url: string     export default url }<\/code><\/pre>\n<p>  <em><b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435.<\/b> \u041b\u0430\u0439\u0444\u0445\u0430\u043a \u043f\u043e\u0434\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u0432 \u043a\u043d\u0438\u0433\u0435 Basarat Ali Syed \u00ab<\/em><a href=\"https:\/\/basarat.gitbook.io\/typescript\/\"><em>TypeScript Deep Dive<\/em><\/a><em>\u00bb. \u041e\u043d\u0430 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0430, \u043d\u043e \u0432\u0441\u0451 \u0435\u0449\u0451 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u0433\u0440\u0443\u0437\u0438\u0442\u044c\u0441\u044f \u0432 TypeScript. \u041e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 TypeScript \u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u0432 <\/em><a href=\"https:\/\/mariusschulz.com\/\"><em>\u0431\u043b\u043e\u0433\u0435<\/em><\/a><em> \u041c\u0430\u0440\u0438\u0443\u0441\u0430 \u0428\u0443\u043b\u044c\u0446\u0430. \u041e\u043d \u043f\u0438\u0448\u0435\u0442 \u043e \u043d\u043e\u0432\u044b\u0445 \u0444\u0438\u0447\u0430\u0445 \u0438 \u043f\u0440\u0438\u0435\u043c\u0430\u0445. \u0422\u0430\u043a\u0436\u0435 \u0438\u0437\u0443\u0447\u0430\u0439\u0442\u0435<\/em><a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/release-notes\/overview.html\"><em> change logs<\/em><\/a><em>, \u0442\u0430\u043c \u0435\u0441\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f\u0445, \u043d\u043e \u0438 \u0442\u043e, \u043a\u0430\u043a \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c.<\/em><\/p>\n<p>  \u041e\u0441\u0442\u0430\u043b\u0438\u0441\u044c actions. \u0417\u0430\u0442\u0438\u043f\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0438 \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445.<\/p>\n<pre><code class=\"javascript\">type FetchAction = {     type: &quot;TASK_FETCH&quot; }  type SuccessAction = {     type: &quot;TASK_SUCCESS&quot;,     payload: Task  type FailAction = {     type: &quot;TASK_FAIL&quot;,     payload: Error }  type Actions = FetchAction | SuccessAction | FailAction<\/code><\/pre>\n<p>  \u041f\u043e\u043b\u0435 <code>type<\/code> \u0443 \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432 \u043e\u043d\u043e \u0440\u0430\u0437\u043d\u043e\u0435, \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e string, \u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u2014 <strong>\u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0439 \u043b\u0438\u0442\u0435\u0440\u0430\u043b<\/strong>. \u042d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 <strong>\u0434\u0438\u0441\u043a\u0440\u0438\u043c\u0438\u043d\u0430\u0442\u043e\u0440<\/strong> \u2014 \u0442\u0435\u0433, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u043a\u0435\u0439\u0441\u044b. \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 discriminated union \u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 payload.<\/p>\n<p>  \u041e\u0431\u043d\u043e\u0432\u0438\u043c \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 Redux-\u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">export const taskReducer = (state: State, action: Actions): State = &gt; {     switch (action.type) {         case &quot;TASK_FETCH&quot;:             return { isFetching: true }         case &quot;TASK_SUCCESS&quot;:             return { isFetching: false, task: action.payload }         case &quot;TASK_FAIL&quot;:             return { isFetching: false, error: action.payload }     }          return state }<\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c \u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u043c <code>string<\/code>\u2026  <\/p>\n<pre><code class=\"javascript\">type FetchAction = {     type: string }<\/code><\/pre>\n<p>\u2026 \u0442\u043e \u0432\u0441\u0435 \u0441\u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u043d\u0435 \u0434\u0438\u0441\u043a\u0440\u0438\u043c\u0438\u043d\u0430\u0442\u043e\u0440.<\/p>\n<p>  \u0412 \u044d\u0442\u043e\u043c action, type \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043e\u043e\u0431\u0449\u0435 \u043b\u044e\u0431\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0439, \u0430 \u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0434\u0438\u0441\u043a\u0440\u0438\u043c\u0438\u043d\u0430\u0442\u043e\u0440\u043e\u043c. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e TypeScript \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u0438\u0442\u044c \u043e\u0434\u0438\u043d action \u043e\u0442 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0438 \u043d\u0430\u0439\u0442\u0438 \u043e\u0448\u0438\u0431\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0434\u0435\u0441\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0439 \u043b\u0438\u0442\u0435\u0440\u0430\u043b. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e: <code>type ActionType = Actions[&quot;type&quot;]<\/code>.<\/p>\n<p>  \u0412 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430\u0445 \u0431\u0443\u0434\u0443\u0442 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0438 \u043d\u0430\u0448\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/uf\/gm\/si\/ufgmsit8lx5zzmmd9tvot5ibg5u.png\"><\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c\u2026  <\/p>\n<pre><code class=\"javascript\">type FetchAction = {     type: string }<\/code><\/pre>\n<p>\u2026 \u0442\u043e \u0432 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e <code>string<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0443\u0436\u0435 \u043d\u0435 \u0432\u0430\u0436\u043d\u044b.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/z1\/g1\/qe\/z1g1qecermtbhjq62vju5ujmwv0.png\"><\/p>\n<p>  \u041c\u044b \u0432\u0441\u0451 \u0437\u0430\u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0442\u0438\u043f \u0441\u0443\u043c\u043c\u0443.<\/p>\n<h2>Exhaustive checking<\/h2>\n<p>  \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0433\u0438\u043f\u043e\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u0432 \u043a\u043e\u0434 \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<pre><code class=\"javascript\">export const taskReducer = (state: State, action: Actions): State = &gt; {     switch (action.type) {         case &quot;TASK_FETCH&quot;:             return { isFetching: true }         case &quot;TASK_SUCCESS&quot;:             return { isFetching: false, task: action.payload }         \/\/case &quot;TASK_FAIL&quot;:             \/\/return { isFetching: false, error: action.payload }     }          return state }<\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 <strong>exhaustive checking<\/strong> \u2014 \u0435\u0449\u0451 \u043e\u0434\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0442\u0438\u043f\u0430 \u0441\u0443\u043c\u043c\u044b<strong>.<\/strong> \u042d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043a\u0435\u0439\u0441\u044b.<\/p>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u0441\u043b\u0435 switch: <code>const exhaustiveCheck: never = action<\/code>.<\/p>\n<p>  never \u2014 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u0442\u0438\u043f:<\/p>\n<ul>\n<li>\u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0440\u043e\u0441\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e);<\/li>\n<li>\u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0442\u0438\u043f, \u0442\u043e \u044d\u0442\u043e\u0442 \u0442\u0438\u043f \u043d\u0435\u043b\u044c\u0437\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0438\u043b\u0438\u0439.<\/li>\n<\/ul>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0443\u043a\u0430\u0436\u0435\u0442 \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0443 \u00abType &#8216;FailAction&#8217; is not assignable to type &#8216;never&#8217;\u00bb. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0442\u0438\u043f\u0430 actions, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u043d\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 <code>&quot;TASK_FAIL&quot;<\/code> \u2014 \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c <code>FailAction<\/code>. \u041d\u043e \u043a never \u043e\u043d \u043d\u0435 \u00abassignable\u00bb.<\/p>\n<p>  \u0414\u043e\u043f\u0438\u0448\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 <code>&quot;TASK_FAIL&quot;<\/code>, \u0438 \u043e\u0448\u0438\u0431\u043a\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 <code>&quot;TASK_FETCH&quot;<\/code> \u2014 \u0432\u0435\u0440\u043d\u0443\u043b\u0438\u0441\u044c, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 <code>&quot;TASK_SUCCESS&quot;<\/code> \u2014 \u0432\u0435\u0440\u043d\u0443\u043b\u0438\u0441\u044c, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 <code>&quot;TASK_FAIL&quot;<\/code>. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432\u0441\u0435 \u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0447\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c action? \u041d\u0438\u0447\u0435\u043c \u2014 <code>never<\/code>.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d action, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u043e\u0434\u0441\u043a\u0430\u0436\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0438\u0437 \u043d\u0438\u0445 \u043d\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442, \u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0432\u0441\u0435 actions, \u0430 \u0435\u0441\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0432\u044b\u0431\u043e\u0440\u043e\u0447\u043d\u044b\u0435, \u0442\u043e \u043d\u0435\u0442.<\/p>\n<h2>\u041f\u0435\u0440\u0432\u044b\u0439 \u0441\u043e\u0432\u0435\u0442<\/h2>\n<blockquote><p>\u0421\u0442\u0430\u0440\u0430\u0439\u0442\u0435\u0441\u044c.<\/p><\/blockquote>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0431\u0443\u0434\u0435\u0442 \u0442\u044f\u0436\u0435\u043b\u043e \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f: \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043e \u0442\u0438\u043f\u0435 \u0441\u0443\u043c\u043c\u044b, \u043f\u043e\u0442\u043e\u043c \u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f\u0445, \u0430\u043b\u0433\u0435\u0431\u0440\u0430\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0442\u0438\u043f\u0430\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442\u0430\u043a \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435. \u041f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0438\u0442\u044c \u0443\u0441\u0438\u043b\u0438\u044f.<\/p>\n<p>  \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u0441\u044f \u0433\u043b\u0443\u0431\u0436\u0435, \u0442\u043e \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u0449\u0438 \u0432\u043e\u0434\u044b \u043d\u0430\u0434 \u043d\u0430\u043c\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f. \u041d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0433\u043b\u0443\u0431\u0438\u043d\u0435 \u0432\u044b\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0449\u0430\u044f \u0441\u0438\u043b\u0430 \u0438 \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u043e\u0434\u044b \u043d\u0430\u0434 \u043d\u0430\u043c\u0438 \u0443\u0440\u0430\u0432\u043d\u043e\u0432\u0435\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f. \u042d\u0442\u043e \u0437\u043e\u043d\u0430 \u00ab\u043d\u0435\u0439\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043b\u0430\u0432\u0443\u0447\u0435\u0441\u0442\u0438\u00bb, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043d\u0435\u0432\u0435\u0441\u043e\u043c\u043e\u0441\u0442\u0438. \u0412 \u044d\u0442\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0434\u0440\u0443\u0433\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c \u0442\u0438\u043f\u043e\u0432 \u0438\u043b\u0438 \u044f\u0437\u044b\u043a\u0430\u043c.<\/p>\n<h2>\u041d\u043e\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0442\u0438\u043f\u043e\u0432<\/h2>\n<p>  \u0412 \u0414\u0440\u0435\u0432\u043d\u0435\u043c \u0420\u0438\u043c\u0435 \u0443 \u0436\u0438\u0442\u0435\u043b\u0435\u0439 \u0431\u044b\u043b\u043e \u0442\u0440\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0445 \u0438\u043c\u0435\u043d\u0438: \u0444\u0430\u043c\u0438\u043b\u0438\u044f, \u0438\u043c\u044f \u0438 \u00ab\u043f\u0440\u043e\u0437\u0432\u0438\u0449\u0435\u00bb. \u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438\u043c\u044f \u2014 \u044d\u0442\u043e \u00ab\u043d\u043e\u043c\u0435\u043d\u00bb. \u041e\u0442 \u044d\u0442\u043e\u0433\u043e \u0438\u0434\u0435\u0442 \u043d\u043e\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0442\u0438\u043f\u043e\u0432 \u2014 \u00ab\u0438\u043c\u0435\u043d\u043d\u0430\u044f\u00bb. \u041e\u043d\u0430 \u0438\u043d\u043e\u0433\u0434\u0430 \u0431\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439.<\/p>\n<p>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<pre><code class=\"javascript\">export const githubUrl = process.env.GITHUB_URL as string export const nodeEnv = process.env.NODE_ENV as string  export const fetchStarredRepos = (     nodeEnv: string,     githubUrl: string ): Promise&lt;GithubRepo[ ]&gt; =&gt; {     if (nodeEnv = &quot;production&quot;) {         \/\/ log call     }      \/\/ prettier-ignore     return fetch('$githubUrl}\/users\/saitonakamura\/starred')         .then(r =&gt; r.json()); }<\/code><\/pre>\n<p>  \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043f\u043e API: <code>GITHUB_URL=https:\/\/api.github.com<\/code>. \u041c\u0435\u0442\u043e\u0434 <code>githubUrl<\/code> \u043f\u043e API \u0434\u043e\u0441\u0442\u0430\u0435\u0442 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0441\u0442\u0430\u0432\u0438\u043c \u00ab\u0437\u0432\u0435\u0437\u0434\u043e\u0447\u043a\u0443\u00bb. \u0410 \u0435\u0441\u043b\u0438 <code>nodeEnv = &quot;production&quot;<\/code>, \u0442\u043e \u043e\u043d \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 \u0432\u044b\u0437\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043c\u0435\u0442\u0440\u0438\u043a.<\/p>\n<p>  \u0414\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c (UI).<\/p>\n<pre><code class=\"javascript\">import React, { useState } from &quot;react&quot;  export const StarredRepos = () =&gt; {     const [starredRepos, setStarredRepos] = useState&lt;GithubRepo[ ] | null&gt;(null)      if (!starredRepos) return &lt;div&gt;Loading\u2026&lt;\/div&gt;      return (         &lt;ul&gt;             {starredRepos.map(repo =&gt; (                 &lt;li key={repo.name}&gt;repo.name}&lt;\/li&gt;             ))}         &lt;\/ul&gt;     ) }  type GithubRepo = {     name: string }<\/code><\/pre>\n<p>  \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0443\u0436\u0435 \u0443\u043c\u0435\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u0430 \u0435\u0441\u043b\u0438 \u0438\u0445 \u043d\u0435\u0442, \u0442\u043e \u043b\u043e\u0430\u0434\u0435\u0440. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c API-\u0432\u044b\u0437\u043e\u0432 \u0438 \u0437\u0430\u0441\u0435\u0442\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<pre><code class=\"javascript\">useEffect(() =&gt; {     fetchStarredRepos(githubUrl, nodeEnv).then(data =&gt; setStarredRepos(data)) }, [ ])<\/code><\/pre>\n<p>  \u041d\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u044d\u0442\u043e \u043a\u043e\u0434 \u2014 \u0432\u0441\u0451 \u0443\u043f\u0430\u0434\u0435\u0442. \u0412 \u043f\u0430\u043d\u0435\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043c, \u0447\u0442\u043e <code>fetch<\/code> \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <code>'\/users\/saitonakamura\/starred'<\/code> \u2014 githubUrl \u043a\u0443\u0434\u0430-\u0442\u043e \u043f\u0440\u043e\u043f\u0430\u043b. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u0438\u0437-\u0437\u0430 \u0441\u0442\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0434\u0438\u0437\u0430\u0439\u043d\u0430 \u2014 <code>nodeEnv<\/code> \u0438\u0434\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u043c. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0441\u043e\u0431\u043b\u0430\u0437\u043d \u0432\u0441\u0435 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c, \u043d\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u044b.<\/p>\n<p>  \u041d\u043e \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043e\u0431 \u044d\u0442\u043e\u043c \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043f\u043e\u0434\u0441\u043a\u0430\u0436\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440? \u0422\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0432\u0435\u0441\u044c \u0446\u0438\u043a\u043b \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043a\u0438, \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0440\u0438\u0447\u0438\u043d.<\/p>\n<h3>\u0411\u0440\u0435\u043d\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<p>  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 TypeScript \u0435\u0441\u0442\u044c \u0445\u0430\u043a \u2014 \u0431\u0440\u0435\u043d\u0434-\u0442\u0438\u043f\u044b. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c <code>Brand<\/code>, <code>B<\/code> (\u0441\u0442\u0440\u043e\u043a\u0430), <code>T<\/code> \u0438 \u0434\u0432\u0430 \u0442\u0438\u043f\u0430. \u0422\u0430\u043a\u043e\u0439 \u0436\u0435 \u0442\u0438\u043f \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u043b\u044f <code>NodeEnv<\/code>.<\/p>\n<pre><code class=\"javascript\">type Brand&lt;T, B extends string&gt; = T &amp; { readonly _brand: B }  type GithubUrl = Brand&lt;string, &quot;githubUrl&quot;&gt; export const githubUrl = process.env.GITHUB_URL as GithubUrl  type NodeEnv = Brand&lt;string, &quot;nodeEnv&quot;&gt; export const nodeEnv = process.env.NODE_ENV as NodeEnv<\/code><\/pre>\n<p>  \u041d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/qi\/_e\/j-\/qi_ej-yne7xhcj4qmozvbw6r7qc.png\"><\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c <code>githubUrl<\/code> \u0438 <code>nodeEnv<\/code> \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u043e\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0438\u043f\u044b. \u041d\u0435\u043a\u0430\u0437\u0438\u0441\u0442\u044b\u0435, \u043d\u043e \u043d\u043e\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0438\u0445 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u0437\u0434\u0435\u0441\u044c \u2014 \u043c\u0435\u043d\u044f\u0435\u043c \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u0430.<\/p>\n<pre><code class=\"javascript\">useEffect(() =&gt; {     fetchStarresRepos(nodeEnv, githubUrl).then(data =&gt; setStarredRepos(data)) }, [ ])<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e \u2014 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 <strong>\u0431\u0440\u0435\u043d\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u044b<\/strong>. \u0411\u0440\u0435\u043d\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 (\u0441\u0442\u0440\u043e\u043a\u0438, \u0447\u0438\u0441\u043b\u0430). \u0423 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0430\u044f \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0430 (x,y \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b), \u0438 \u0438\u0445 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0443\u0442\u0430\u0442\u044c. \u0423\u0434\u043e\u0431\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u043e\u043d\u0438 \u043f\u0435\u0440\u0435\u043f\u0443\u0442\u0430\u043d\u044b.<\/p>\n<p>  \u041d\u043e \u0437\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c \u0434\u0432\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u041f\u0435\u0440\u0432\u0430\u044f \u2014 \u0432 TypeScript \u043d\u0435\u0442 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043d\u043e\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432. \u041d\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u0434\u0430, \u0447\u0442\u043e \u043e\u043d\u0430 \u0440\u0435\u0448\u0438\u0442\u0441\u044f, \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u044f\u0437\u044b\u043a\u0430 \u0438\u0434\u0451\u0442 <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/33038\">\u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u0430<\/a>.<\/p>\n<p>  \u0412\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u2014 \u00abas\u00bb, \u043d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0439, \u0447\u0442\u043e \u0432 <code>GITHUB_URL<\/code> \u043d\u0435 \u0431\u0438\u0442\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430.<\/p>\n<p>  \u0422\u0430\u043a\u0436\u0435, \u043a\u0430\u043a \u0438 \u0441 <code>NODE_ENV<\/code>. \u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0443, \u0430 <code>&quot;production&quot;<\/code> \u0438\u043b\u0438 <code>&quot;development&quot;<\/code>.<\/p>\n<pre><code class=\"javascript\">type NodeEnv = Brand&lt;&quot;production&quot; | &quot;development&quot; | &quot;nodeEnv&quot;&gt; export const nodeEnv = process.env.NODE_ENV as NodeEnv<\/code><\/pre>\n<p>  \u0412\u0441\u0451 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c. \u041e\u0442\u0441\u044b\u043b\u0430\u044e \u0432\u0430\u0441 \u043a \u0441\u043c\u0430\u0440\u0442-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430\u043c \u0438 \u0434\u043e\u043a\u043b\u0430\u0434\u0443 \u0421\u0435\u0440\u0433\u0435\u044f \u0427\u0435\u0440\u0435\u043f\u0430\u043d\u043e\u0432\u0430 \u00ab<a href=\"https:\/\/youtu.be\/cT-VOwWjJJs\">\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043d\u0430 TypeScript \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0442\u0438\u043b\u0435<\/a>\u00bb.<\/p>\n<h2>\u0412\u0442\u043e\u0440\u043e\u0439 \u0438 \u0442\u0440\u0435\u0442\u0438\u0439 \u0441\u043e\u0432\u0435\u0442\u044b<\/h2>\n<blockquote><p>\u0411\u0443\u0434\u044c\u0442\u0435 \u0431\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b.<\/p><\/blockquote>\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0432\u043e\u043a\u0440\u0443\u0433: \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0435 \u044f\u0437\u044b\u043a\u0438, \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0438, \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0442\u0438\u043f\u043e\u0432. \u0418\u0437\u0443\u0447\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0438 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0439\u0442\u0435 \u0443\u0440\u043e\u043a\u0438.<\/p>\n<p>  \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043c \u0442\u043e\u0447\u043a\u0443 \u00ab\u043d\u0435\u0439\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043b\u0430\u0432\u0443\u0447\u0435\u0441\u0442\u0438\u00bb, \u0432\u043e\u0434\u0430 \u0434\u0430\u0432\u0438\u0442 \u0432\u0441\u0451 \u0441\u0438\u043b\u044c\u043d\u0435\u0435 \u0438 \u043d\u0430\u0441 \u0442\u044f\u043d\u0435\u0442 \u0432\u043d\u0438\u0437.  <\/p>\n<blockquote><p>\u0420\u0430\u0441\u0441\u043b\u0430\u0431\u044c\u0442\u0435\u0441\u044c.<\/p><\/blockquote>\n<p>\u041f\u043e\u0433\u0440\u0443\u0436\u0430\u0439\u0442\u0435\u0441\u044c \u0433\u043b\u0443\u0431\u0436\u0435 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044c\u0442\u0435 TypeScript \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0430\u0431\u043e\u0442\u0443.<\/p>\n<h2>\u0427\u0442\u043e \u0443\u043c\u0435\u0435\u0442 TypeScript<\/h2>\n<p>  TypeScript \u0443\u043c\u0435\u0435\u0442 <strong>\u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0438\u043f\u044b<\/strong>.<\/p>\n<pre><code class=\"javascript\">export const createFetch = () =&gt; ({     type: &quot;TASK_FETCH&quot; })  export const createSuccess = (task: Task) =&gt; ({     type: &quot;TASK_SUCCESS&quot;     payload: Task })  export const createFail = (error: Error) =&gt; ({     type: &quot;TASK_FAIL&quot;     payload: error })  type FetchAction = {     type: &quot;TASK_FETCH&quot;,  type SuccessAction = {     type: &quot;TASK_SUCCESS&quot;,     payload: Task  type FailAction = {     type: &quot;TASK_FAIL&quot;,     payload: Error }<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 TypeScript \u0435\u0441\u0442\u044c <code>ReturnType<\/code> \u2014 \u043e\u043d \u0434\u043e\u0441\u0442\u0430\u0435\u0442 \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435: <\/p>\n<pre><code class=\"javascript\">type FetchAction = ReturnType&lt;typeof createFetch&gt;<\/code><\/pre>\n<p>\u0412 \u043d\u0451\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0442\u0438\u043f \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041f\u0440\u043e\u0441\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c: \u0447\u0442\u043e\u0431\u044b \u0432\u0437\u044f\u0442\u044c \u0442\u0438\u043f \u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c <code>typeof<\/code>.<\/p>\n<p>  \u0412 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430\u0445 \u0432\u0438\u0434\u0438\u043c <code>type: string<\/code>.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/6w\/n0\/tq\/6wn0tq3zjhnnoqvjrk0saubafak.png\"><\/p>\n<p>  \u042d\u0442\u043e \u043f\u043b\u043e\u0445\u043e \u2014 \u0434\u0438\u0441\u043a\u0440\u0438\u043c\u0438\u043d\u0430\u0442\u043e\u0440 \u0441\u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0439 \u043b\u0438\u0442\u0435\u0440\u0430\u043b.<\/p>\n<pre><code class=\"javascript\">export const createFetch = () =&gt; ({     type: &quot;TASK_FETCH&quot; })<\/code><\/pre>\n<p>  \u041a\u043e\u0433\u0434\u0430 \u0432 JavaScript \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u043d \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u044b\u0439. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u0441 \u043f\u043e\u043b\u0435\u043c \u0438 \u0441\u0442\u0440\u043e\u043a\u043e\u0439, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0437\u0436\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 TypeScript \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0434\u043e \u043b\u044e\u0431\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u043b\u044f \u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/p>\n<p>  \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u043f\u043e\u043c\u043e\u0447\u044c TypeScript. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c as const.<\/p>\n<pre><code class=\"javascript\">export const createFetch = ( ) =&gt; ({     type: &quot;TASK_FETCH&quot; as const })<\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u2014 \u0432 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430\u0445 \u0441\u0440\u0430\u0437\u0443 \u0438\u0441\u0447\u0435\u0437\u043d\u0435\u0442 string. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u043f\u0440\u043e\u0442\u0438\u0432 \u0441\u0442\u0440\u043e\u043a\u0438, \u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u0430.<\/p>\n<pre><code class=\"javascript\">export const createFetch = ( ) =&gt; ({     type: &quot;TASK_FETCH&quot; } as const)<\/code><\/pre>\n<p>  \u0422\u043e\u0433\u0434\u0430 \u0442\u0438\u043f (\u0438 \u0432\u0441\u0435 \u043f\u043e\u043b\u044f) \u0441\u0442\u0430\u043d\u0443\u0442 readonly.<\/p>\n<pre><code class=\"javascript\">type FetchAction = {     readonly type: &quot;TASK_FETCH&quot;; }<\/code><\/pre>\n<p>  \u042d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432\u0440\u044f\u0434 \u043b\u0438 \u0432\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0432\u043e\u0435\u0433\u043e action. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c as const \u0432\u0435\u0437\u0434\u0435.<\/p>\n<pre><code class=\"javascript\">export const createFetch = () =&gt; ({     type: &quot;TASK_FETCH&quot; } as const)  export const createSuccess = (task: Task) =&gt; ({     type: &quot;TASK_SUCCESS&quot;     payload: Task } as const)  export const createFail = (error: Error) =&gt; ({     type: &quot;TASK_FAIL&quot;     payload: error } as const)  type Actions =     | ReturnType&lt;typeof createFetch&gt;     | ReturnType&lt;typeof createSuccess&gt;     | ReturnType&lt;typeof createFail&gt;  type State =     | { isFetching: true }     | { isFetching: false; task: Task }     | { isFetching: false; error: Error }  export const taskReducer = (state: State, action: Actions): State = &gt; {     switch (action.type) {         case &quot;TASK_FETCH&quot;:             return { isFetching: true }         case &quot;TASK_SUCCESS&quot;:             return { isFetching: false, task: action.payload }         case &quot;TASK_FAIL&quot;:             return { isFetching: false, error: action.payload } }    const _exhaustiveCheck: never = action    return state }<\/code><\/pre>\n<p>  \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438 actions \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 as const. \u0412\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 TypeScript \u043f\u043e\u043d\u044f\u043b \u0441\u0430\u043c.<\/p>\n<p>  TypeScript \u0443\u043c\u0435\u0435\u0442 <strong>\u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c State<\/strong>. \u041e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435\u043c \u0432 \u043a\u043e\u0434\u0435 \u0432\u044b\u0448\u0435 \u0442\u0440\u0435\u043c\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438 isFetching: true, false \u0438\u043b\u0438 Task.<\/p>\n<p>  \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c type State = ReturnType. \u0412 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430\u0445 TypeScript \u0443\u043a\u0430\u0436\u0435\u0442, \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ve\/jk\/vu\/vejkvuzbnzraxku1y7yfm5qefhu.png\"><\/p>\n<p>  \u0421\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u043c.<\/p>\n<pre><code class=\"javascript\">type State = ReturnType&lt;typeof taskReducer&gt;  export const taskReducer = (state, action: Actions) =&gt; {     switch (action.type) {         case &quot;TASK_FETCH&quot;:             return { isFetching: true }         case &quot;TASK_SUCCESS&quot;:             return { isFetching: false, task: action.payload }         case &quot;TASK_FAIL&quot;:             return { isFetching: false, error: action.payload } }  const _exhaustiveCheck: never = action  return state }<\/code><\/pre>\n<p>  <code>State<\/code> \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b \u0440\u0443\u0433\u0430\u0442\u044c\u0441\u044f, \u043d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d <code>any<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c. \u0422\u0438\u043f\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442.<\/p>\n<pre><code class=\"javascript\">type State = ReturnType&lt;typeof taskReducer&gt;  export const taskReducer = (state: { isFetching: true }, action: Actions) =&gt; {     switch (action.type) {         case &quot;TASK_FETCH&quot;:             return { isFetching: true }         case &quot;TASK_SUCCESS&quot;:             return { isFetching: false, task: action.payload }         case &quot;TASK_FAIL&quot;:             return { isFetching: false, error: action.payload } }  const _exhaustiveCheck: never = action  return state }<\/code><\/pre>\n<p>  \u0412\u044b\u0432\u043e\u0434 \u0433\u043e\u0442\u043e\u0432.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/i-\/7f\/mt\/i-7fmtcvakp9l6ldfo98cqxfbwy.png\"><\/p>\n<p>  \u0412\u044b\u0432\u043e\u0434 \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e: <code>true<\/code>, <code>false<\/code>, <code>Task<\/code>. \u0417\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c \u043c\u0443\u0441\u043e\u0440\u043d\u044b\u0435 \u043f\u043e\u043b\u044f <code>Error<\/code>, \u043d\u043e \u0441 \u0442\u0438\u043f\u043e\u043c <code>undefined<\/code> \u2014 \u043f\u043e\u043b\u0435 \u0432\u0440\u043e\u0434\u0435 \u0435\u0441\u0442\u044c, \u0430 \u0432\u0440\u043e\u0434\u0435 \u0438 \u043d\u0435\u0442.<\/p>\n<h2>\u0427\u0435\u0442\u0432\u0435\u0440\u0442\u044b\u0439 \u0441\u043e\u0432\u0435\u0442<\/h2>\n<blockquote><p>\u041d\u0435 \u043f\u0435\u0440\u0435\u0442\u0440\u0443\u0436\u0434\u0430\u0439\u0442\u0435\u0441\u044c.<\/p><\/blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0440\u0430\u0441\u0441\u043b\u0430\u0431\u0438\u0442\u044c\u0441\u044f \u0438 \u043d\u044b\u0440\u043d\u0443\u0442\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0433\u043b\u0443\u0431\u043e\u043a\u043e, \u043a\u0438\u0441\u043b\u043e\u0440\u043e\u0434\u0430 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e.<\/p>\n<p>  \u0412 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0438 \u0442\u0430\u043a\u0436\u0435: \u0435\u0441\u043b\u0438 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043f\u043e\u0433\u0440\u0443\u0437\u0438\u0442\u044c\u0441\u044f \u0432 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e \u0438 \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0435 \u0432\u0435\u0437\u0434\u0435, \u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u0442\u043e\u043b\u043a\u043d\u0435\u0442\u0435\u0441\u044c \u0441 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438, \u043f\u0440\u0438\u0447\u0438\u043d\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442\u0435. \u042d\u0442\u043e \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u043e\u0442\u0442\u043e\u0440\u0436\u0435\u043d\u0438\u0435, \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0437\u0430\u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0438\u043f\u044b. \u0421\u0442\u0430\u0440\u0430\u0439\u0442\u0435\u0441\u044c \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0438\u043b\u044b.<\/p>\n<h2>\u041d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e TypeScript \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443<\/h2>\n<p>  \u041a\u0430\u043a\u043e\u0435-\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438. \u0423 \u043d\u0435\u0435 \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u043b\u0443\u0447\u0448\u0438\u0439 UX \u2014 \u0438\u043d\u043e\u0433\u0434\u0430 \u043e\u043d\u0430 \u0432\u044b\u0434\u0430\u0435\u0442 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043a\u0430\u043a \u0438 \u043b\u044e\u0431\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0442\u0438\u043f\u043e\u0432, \u043a\u0430\u043a \u0432\u043e Flow \u0438\u043b\u0438 Haskell.  <\/p>\n<blockquote><p>\u0427\u0435\u043c \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u0435\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u0430, \u0442\u0435\u043c \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u043e\u0448\u0438\u0431\u043a\u0438.<\/p><\/blockquote>\n<p>\u0426\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0442\u0438\u043f\u043e\u0432 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u043d\u0430 \u0432\u044b\u0434\u0430\u0451\u0442 \u0431\u044b\u0441\u0442\u0440\u0443\u044e \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c \u043f\u0440\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a. \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0438, \u0438 \u0443\u0439\u0434\u0435\u0442 \u043c\u0435\u043d\u044c\u0448\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430 \u0438\u0445 \u043f\u043e\u0438\u0441\u043a \u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435. \u0415\u0441\u043b\u0438 \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043e\u043a, \u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u0422\u0438\u043f\u044b \u043d\u0435 \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u044e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443, \u0435\u0441\u043b\u0438 \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0441 \u043d\u0438\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<blockquote><p>\u0421\u043d\u043e\u0432\u0430 \u0441\u043a\u043e\u0440\u043e \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u043d\u043e\u0432\u044b\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u0438 \u043d\u044b\u0440\u044f\u0442\u044c \u043f\u043e\u0433\u043b\u0443\u0431\u0436\u0435 \u0432 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043d\u0430 <a href=\"https:\/\/ritfest.ru\/2020\">\u0420\u0418\u0422++<\/a>. \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043e\u043d\u043b\u0430\u0439\u043d-\u0444\u0435\u0441\u0442\u0438\u0432\u0430\u043b\u044c \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442, \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0441\u0435\u0440\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u0445 \u043a\u0440\u0443\u0433\u043e\u0437\u043e\u0440 \u0434\u043e\u043a\u043b\u0430\u0434\u043e\u0432 (25 \u0438 26 \u043c\u0430\u044f) \u0438 \u043c\u0430\u0441\u0442\u0435\u0440-\u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0434\u043b\u044f \u0433\u043b\u0443\u0431\u043e\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 (27 \u043c\u0430\u044f \u2014 10 \u0438\u044e\u043d\u044f). <\/p>\n<p>  <a href=\"https:\/\/conf.ontico.ru\/conference\/join\/rit2020.html?popup=5\">\u0426\u0435\u043d\u044b \u043d\u0430 \u0431\u0438\u043b\u0435\u0442\u044b<\/a> \u0441\u043d\u0438\u0436\u0435\u043d\u044b \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e (5900 \u0434\u043b\u044f \u0444\u0438\u0437\u043b\u0438\u0446\u0430), \u0447\u0442\u043e \u0420\u0418\u0422++ \u0441\u0442\u0430\u043b \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0438 \u0431\u044b\u0441\u0442\u0440\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u0441\u0440\u0435\u0437 \u0432\u0441\u0435\u0439 IT-\u0438\u043d\u0434\u0443\u0441\u0442\u0440\u0438\u0438, \u043d\u043e \u0438 \u043e\u0447\u0435\u043d\u044c \u0432\u044b\u0433\u043e\u0434\u043d\u044b\u043c. <\/p>\n<p>  \u0410 \u0435\u0449\u0435 \u043f\u0440\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 <a href=\"https:\/\/habr.com\/ru\/company\/avito\/\">AvitoTech<\/a> \u0432\u0438\u0434\u0435\u043e\u0437\u0430\u043f\u0438\u0441\u0438 FrontendConf 2019 \u0442\u0435\u043f\u0435\u0440\u044c \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435. \u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0438\u0445 \u043d\u0430 <a href=\"https:\/\/www.youtube.com\/playlist?list=PLfbxrJr-t5mn1fAypCWIVKass-X7ru0iR\">youtube-\u043a\u0430\u043d\u0430\u043b\u0435<\/a> \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u043d\u0430 <a href=\"http:\/\/eepurl.com\/bb99tn\">\u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0443<\/a> \u0438\u043b\u0438 telegram <a href=\"https:\/\/t.me\/FrontendConfChannel\">@FrontendConfChannel<\/a>, \u0447\u0442\u043e\u0431\u044b \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043d\u0435 \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043d\u043e\u0432\u043e\u0441\u0442\u0438. <\/p><\/blockquote>\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\/company\/oleg-bunin\/blog\/499634\/\"> https:\/\/habr.com\/ru\/company\/oleg-bunin\/blog\/499634\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/oleg-bunin\/blog\/499634\/\">\u0424\u0440\u0438\u0434\u0430\u0439\u0432\u0438\u043d\u0433 \u2014 \u043d\u044b\u0440\u044f\u043d\u0438\u0435 \u043d\u0430 \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u0431\u0435\u0437 \u0430\u043a\u0432\u0430\u043b\u0430\u043d\u0433\u0430. \u041d\u044b\u0440\u044f\u043b\u044c\u0449\u0438\u043a \u043e\u0449\u0443\u0449\u0430\u0435\u0442 \u043d\u0430 \u0441\u0435\u0431\u0435 \u0437\u0430\u043a\u043e\u043d \u0410\u0440\u0445\u0438\u043c\u0435\u0434\u0430: \u043e\u043d \u0432\u044b\u0442\u0435\u0441\u043d\u044f\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u044a\u0451\u043c \u0432\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0442\u043d\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u044b\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u0440\u043e\u0432 \u0434\u0430\u044e\u0442\u0441\u044f \u0442\u044f\u0436\u0435\u043b\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u043d\u043e \u043f\u043e\u0442\u043e\u043c \u0441\u0438\u043b\u0430 \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u043b\u0449\u0438 \u0432\u043e\u0434\u044b \u043d\u0430\u0434 \u0442\u043e\u0431\u043e\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c \u0434\u0432\u0438\u0433\u0430\u0442\u044c\u0441\u044f \u0433\u043b\u0443\u0431\u0436\u0435. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0442\u0438\u043f\u043e\u0432 TypeScript \u2014 \u043f\u043e \u043c\u0435\u0440\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043b\u0435\u0433\u0447\u0435. \u041d\u043e \u043d\u0430\u0434\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u0432\u043e\u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043d\u044b\u0440\u043d\u0443\u0442\u044c.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/sh\/eb\/y9\/sheby96u0qt6o3usirdpsc78hpg.jpeg\"><br \/>  <font color=\"gray\"><i>\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f \u0441 \u0441\u0430\u0439\u0442\u0430 <a href=\"https:\/\/www.oneoceanonebreath.com\/freediving-photography\">One Ocean One Breath<\/a>.<\/i><\/font><\/p>\n<p>  <strong>\u041c\u0438\u0445\u0430\u0438\u043b \u0411\u0430\u0448\u0443\u0440\u043e\u0432<\/strong> (<a href=\"https:\/\/habr.com\/ru\/users\/saitonakamura\/\" class=\"user_link\">saitonakamura<\/a>) \u2014 Senior Frontend Engineer \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 WiseBits, \u0444\u0430\u043d\u0430\u0442 TypeScript \u0438 \u0444\u0440\u0438\u0434\u0430\u0439\u0432\u0435\u0440-\u043b\u044e\u0431\u0438\u0442\u0435\u043b\u044c. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f TypeScript \u0438 \u043d\u044b\u0440\u044f\u043d\u0438\u044f \u043d\u0430 \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u043d\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b. \u041c\u0438\u0445\u0430\u0438\u043b \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 discriminated unions, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0432\u043e\u0434 \u0442\u0438\u043f\u043e\u0432, \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u0430 \u043d\u043e\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0438 \u0431\u0440\u0435\u043d\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. \u0417\u0430\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u0434\u044b\u0445\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0439\u0442\u0435\u0441\u044c.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-302742","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/302742","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=302742"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/302742\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=302742"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=302742"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=302742"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}