{"id":312761,"date":"2020-11-08T21:01:39","date_gmt":"2020-11-08T21:01:39","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=312761"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=312761","title":{"rendered":"Typescript: \u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432 \u0432 \u0433\u043b\u0443\u0431\u0438\u043d\u0443"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u041f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0432 TypeScript \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 generic-\u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 key-value \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430: \u044f \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043e \u043d\u0435 \u0441\u0442\u0430\u043b \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 (\u0432\u0440\u043e\u0434\u0435 generic, key-value), \u0442.\u043a., \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430.<\/em><\/p>\n<h3>TLDR:<\/h3>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043b\u044f <code>DeepMergeTwoTypes<\/code> \u0431\u0443\u0434\u0435\u0442 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438. \u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0435\u0433\u043e \u0432 \u0432\u0430\u0448\u0443 IDE, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0441 \u043d\u0438\u043c.<\/p>\n<p>\u041a\u0430\u043a \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432 vsCode:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/23c\/1de\/cce\/23c1deccebb74c56ba32d89444b7f43a\" width=\"880\" height=\"317\"><figcaption><\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0443\u0432\u0435\u0440\u0435\u043d\u044b \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u043e\u0437\u043d\u0430\u043d\u0438\u044f\u0445 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 generic-\u0438 \u0432 TypeScript, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f <a href=\"https:\/\/kuba-svehla.medium.com\/minimalist-typescript-generics-173d09da66b4\" rel=\"noopener noreferrer nofollow\">\u0441 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0451\u0439<\/a> (Miniminalist Typescript &#8212; Generics)<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0435\u0433\u043e \u0432 \u0432\u0430\u0448\u0443 IDE (<em>\u043f\u0440\u0438\u043c. \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430: \u0438\u043b\u0438 \u0432 <\/em><a href=\"https:\/\/www.typescriptlang.org\/play\" rel=\"noopener noreferrer nofollow\"><em>TypeScript Playground \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0443<\/em><\/a>).<\/p>\n<h3>Disclaimer<\/h3>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043e\u0434 \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432 production \u0432\u044b \u0434\u0435\u043b\u0430\u0435\u0442\u0435 \u044d\u0442\u043e \u043d\u0430 \u0441\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u0445 \u0438 \u0440\u0438\u0441\u043a (\u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043c\u044b \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c).<\/p>\n<h3>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f &amp;-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0432 Typescript<\/h3>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0434\u0432\u0430 \u0442\u0438\u043f\u0430 <code>A<\/code> \u0438 <code>B<\/code> \u0438 \u043d\u043e\u0432\u044b\u0439 \u0442\u0438\u043f <code>C<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f <code>A &amp; B<\/code><\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: string, key3: string } type C = A &amp; B const a = (c: C) =&gt; c.<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/47b\/ae8\/ece\/47bae8ece52e2752a13fad460b854773\" width=\"770\" height=\"394\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0441\u0451 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u0432\u044b \u043d\u0435 \u043d\u0430\u0447\u043d\u0451\u0442\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: null, key3: string } type C = A &amp; B<\/code><\/pre>\n<p>\u0422\u0438\u043f <code>A<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 <code>key2<\/code> \u043a\u0430\u043a \u0441\u0442\u0440\u043e\u043a\u0443, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0432 \u0442\u0438\u043f\u0435 <code>B<\/code> \u044d\u0442\u043e <code>null<\/code>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/58b\/a89\/3c1\/58ba893c1b702fb2879f7f679f4cae85\" width=\"736\" height=\"258\"><figcaption><\/figcaption><\/figure>\n<p>Typescript \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043a\u0430\u043a <code>never<\/code> \u0438 \u0442\u0438\u043f <code>C<\/code> \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0451\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u0412 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u043b\u0438 \u0447\u0435\u0433\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u044d\u0442\u043e\u0433\u043e:<\/p>\n<pre><code class=\"javascript\">type ExpectedType = {   key1: string | null,   key2: string,   key3: string }<\/code><\/pre>\n<h3>\u041f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0451\u043c \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f generic-\u0442\u0438\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u0442\u0438\u043f\u044b Typescript. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c 2 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 generic-\u0442\u0438\u043f\u0430.<\/p>\n<h4>GetObjDifferentKeys&lt;&gt;<\/h4>\n<pre><code class=\"javascript\">type GetObjDifferentKeys&lt;T, U&gt; = Omit&lt;T, keyof U&gt; &amp; Omit&lt;U, keyof T&gt;<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 2 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0438\u0437 <code>A<\/code> \u0438 <code>B<\/code>.<\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: null, key3: string }  type C = GetObjDifferentKeys&lt;A, B&gt;['']<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/33a\/0e0\/f75\/33a0e0f75c761096912f01c20cc33a0e\" width=\"858\" height=\"324\"><figcaption><\/figcaption><\/figure>\n<h4>GetObjSameKeys&lt;&gt;<\/h4>\n<p>\u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u0432\u0435\u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 generic-\u0443 \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u0434\u0440\u0443\u0433\u043e\u0439 \u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0442\u0430\u0449\u0438\u0442 \u0432\u0441\u0435 \u043a\u043b\u044e\u0447\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0441\u0442\u044c \u0432 \u043e\u0431\u043e\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u0445.<\/p>\n<pre><code class=\"javascript\">type GetObjSameKeys&lt;T, U&gt; = Omit&lt;T | U, keyof GetObjDifferentKeys&lt;T, U&gt;&gt;<\/code><\/pre>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f \u2014 \u043e\u0431\u044a\u0435\u043a\u0442.<\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: null, key3: string } type C = GetObjSameKeys&lt;A, B&gt;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/381\/e60\/774\/381e6077472445fe9f350dbb9248f272\" width=\"764\" height=\"425\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0441\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0433\u043e\u0442\u043e\u0432\u044b, \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e generic-\u0442\u0438\u043f\u0430 <code>DeepMergeTwoTypes<\/code><\/p>\n<p><code>DeepMergeTwoTypes&lt;&gt;<\/code><\/p>\n<pre><code class=\"javascript\">type DeepMergeTwoTypes&lt;T, U&gt; =   \/\/ \"\u043d\u0435 \u043e\u0431\u0449\u0438\u0435\" (\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435) \u043a\u043b\u044e\u0447\u0438 - \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b   Partial&lt;GetObjDifferentKeys&lt;T, U&gt;&gt;   \/\/ \u043e\u0431\u0449\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 - \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b   &amp; { [K in keyof GetObjSameKeys&lt;T, U&gt;]: T[K] | U[K] }<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 generic \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u0435 &#171;\u043d\u0435 \u043e\u0431\u0449\u0438\u0435&#187; \u043a\u043b\u044e\u0447\u0438 \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 <code>T<\/code> \u0438 <code>U<\/code>, \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0445 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 (\u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438). \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u044d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c\u0443 \u0442\u0438\u043f\u0443 <code>Partial&lt;&gt;<\/code>, \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Typescript. \u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u0441 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f (\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c <code>&amp;<\/code>-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430) \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u043c \u0432\u0441\u0435 \u043e\u0431\u0449\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u043c\u0435\u0436\u0434\u0443 <code>T<\/code> \u0438 <code>U<\/code> , \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 <code>T[K] | U[K]<\/code>.<\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0438\u0436\u0435. \u041d\u043e\u0432\u044b\u0439 generic \u043d\u0430\u0448\u0451\u043b &#171;\u043d\u0435-\u043e\u0431\u0449\u0438\u0435&#187; \u043a\u043b\u044e\u0447\u0438 \u0438 \u0441\u0434\u0435\u043b\u0430\u043b \u0438\u0445 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 (<code>?<\/code>), \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0441\u0442\u0440\u043e\u0433\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b.<\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: null, key3: string } const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c.<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a1b\/38c\/af5\/a1b38caf560a4698a78f825517a61e7b\" width=\"770\" height=\"280\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u043e \u043d\u0430\u0448&nbsp;<code>DeepMergeTwoTypes<\/code>&nbsp;generic \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0441\u043e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\u043c\u0438. \u0422\u0430\u043a \u0447\u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432 \u043d\u043e\u0432\u044b\u0439 generic \u0442\u0438\u043f&nbsp;<code>MergeTwoObjects<\/code>&nbsp;\u0438 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c&nbsp;<code>DeepMergeTwoTypes<\/code>&nbsp;\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043e\u043d \u043d\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442 \u0432\u0441\u0435 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<pre><code class=\"javascript\">\/\/ \u044d\u0442\u043e\u0442 generic \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 DeepMergeTwoTypes&lt;&gt; type MergeTwoObjects&lt;T, U&gt; =   \/\/ \"\u043d\u0435 \u043e\u0431\u0449\u0438\u0435\" (\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435) \u043a\u043b\u044e\u0447\u0438 - \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b   Partial&lt;GetObjDifferentKeys&lt;T, U&gt;&gt;   \/\/ \u043e\u0431\u0449\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 - \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b   &amp; {[K in keyof GetObjSameKeys&lt;T, U&gt;]: DeepMergeTwoTypes&lt;T[K], U[K]&gt;}  export type DeepMergeTwoTypes&lt;T, U&gt; =   \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043b\u0438 \u0442\u0438\u043f\u044b \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438, \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e   [T, U] extends [{ [key: string]: unknown }, { [key: string]: unknown } ]     ? MergeTwoObjects&lt;T, U&gt;     : T | U<\/code><\/pre>\n<p><strong><em>PRO TIP<\/em><\/strong><em>: \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 DeepMergeTwoTypes \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f if-else \u0443\u0441\u043b\u043e\u0432\u0438\u0435 (<\/em><code>extends ?:<\/code>)<em> \u041c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0447\u0442\u043e \u0438 <\/em><code>T<\/code> \u0438 <code>U<\/code> \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u044e\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u044e, \u0437\u0430\u0441\u0443\u043d\u0443\u0432 \u0438\u0445 \u0432 \u043a\u043e\u0440\u0442\u0435\u0436 (tuple) <code>[T, U]<\/code>. \u042d\u0442\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 <code>&amp;&amp;<\/code>-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0432 Javascript.<\/p>\n<p>\u042d\u0442\u043e\u0442 generic \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u043e\u0431\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0438\u043f\u0443&nbsp;<code>{ [key: string]: unknown }<\/code>&nbsp;(\u044d\u0442\u043e&nbsp;<code>Object<\/code>). \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0442\u0430\u043a, \u0442\u043e \u043e\u043d \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0438\u0445 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c&nbsp;<code>MergeTwoObject&lt;&gt;<\/code>. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430: \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 <\/em><code>extends { [key: string]: unknown }<\/code><em> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0435-\u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0442.\u0435. \u0441\u0442\u0440\u043e\u043a\u0438, \u0447\u0438\u0441\u043b\u0430, booleans \u0438 \u0442.\u0434.. <\/em><\/p>\n<p>\u0418 \u0432\u0443\u0430\u043b\u044f! \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 generic \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0451\u043d \u043a\u043e \u0432\u0441\u0435\u043c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c. \u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"javascript\">type A = { key: { a: null, c: string} } type B = { key: { a: string, b: string} } const fn = (c: MergeTwoObjects&lt;A, B&gt;) =&gt; c.key.<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d03\/f84\/5f8\/d03f845f8a25a4c2634a673b18dcf03d\" width=\"770\" height=\"285\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0451?<\/p>\n<p>\u0423\u0432\u044b, \u043d\u0435\u0442. \u041d\u0430\u0448 \u043d\u043e\u0432\u044b\u0439 generic \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043c\u0430\u0441\u0441\u0438\u0432\u044b.<\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435, \u0447\u0435\u043c \u043c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e <code>infer<\/code> (to infer &#8212; \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c).<\/p>\n<p><code>infer<\/code>&nbsp;\u0441\u043c\u043e\u0442\u0440\u0438\u0442 \u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u0442 \u0435\u0451 \u0442\u0438\u043f (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432). \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u043e&nbsp;<code>infer<\/code>&nbsp;\u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/release-notes\/typescript-2-8.html#type-inference-in-conditional-types\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a> (Type inference in conditional types).<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <code>infer<\/code>. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0438\u043f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0432\u0437\u044f\u0442\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 (<code>Item<\/code>):<\/p>\n<pre><code class=\"javascript\">export type ArrayElement&lt;A&gt; = A extends (infer T)[] ? T : never  \/\/ Item === (number | string) type Item = ArrayElement&lt;(number | string)[]&gt;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u044d\u0442\u0438 \u0434\u0432\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u0442\u0438\u043f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0430. \u0418 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c&nbsp;<code>DeepMergeTwoTypes<\/code>&nbsp;\u0434\u043b\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432.<\/p>\n<pre><code class=\"javascript\">export type DeepMergeTwoTypes&lt;T, U&gt; =   \/\/ ----- 2 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 ------   \/\/ \u044d\u0442\u0430 \u23ec   [T, U] extends [(infer TItem)[], (infer UItem)[]]     \/\/ ... \u0438 \u044d\u0442\u0430 \u23ec     ? DeepMergeTwoTypes&lt;TItem, UItem&gt;[]     : ... rest of previous generic ...<\/code><\/pre>\n<p> \u0421\u0435\u0439\u0447\u0430\u0441 <code>DeepMergeTwoTypes<\/code> \u043c\u043e\u0436\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0430\u043c \u0441\u0435\u0431\u044f, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u044b.<\/p>\n<pre><code class=\"javascript\">type A = [{ key1: string, key2: string }] type B = [{ key2: null, key3: string }] const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c[0].<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/928\/a8b\/be2\/928a8bbe2aa777160a7b9ec2cb73c3ca\" width=\"770\" height=\"270\"><figcaption><\/figcaption><\/figure>\n<p>\u0418 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442! \u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0451?<\/p>\n<p>\u042d\u0445&#8230; \u041d\u0435\u0442. \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 <code>Nullable<\/code> \u0442\u0438\u043f\u043e\u0432 \u0441 <code>non-nullable<\/code>. <\/p>\n<pre><code class=\"javascript\">type A = { key1: string } type B = { key1: undefined }  type C = DeepMergeTwoTypes&lt;A, B&gt;['key']<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e98\/d00\/d9e\/e98d00d9eae109c2b07c3be5f403ba2e\" width=\"770\" height=\"318\"><figcaption><\/figcaption><\/figure>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f \u2014 <code>string | undefined<\/code>, \u043d\u043e \u043d\u0430 \u0434\u0435\u043b\u0435 \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0451 \u0434\u0432\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u043d\u0430\u0448\u0443 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 <code>if-else<\/code> .<\/p>\n<pre><code class=\"javascript\">export type DeepMergeTwoTypes&lt;T, U&gt; =   [T, U] extends [(infer TItem)[], (infer UItem)[]]     ? DeepMergeTwoTypes&lt;TItem, UItem&gt;[]     : [T, U] extends [{ [key: string]: unknown}, { [key: string]: unknown } ]       ? MergeTwoObjects&lt;T, U&gt;       \/\/ ----- 2 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 ------       \/\/ \u044d\u0442\u0430 \u23ec       : [T, U] extends [           { [key: string]: unknown } | undefined,            { [key: string]: unknown } | undefined          ]         \/\/ ... \u0438 \u044d\u0442\u0430 \u23ec         ? MergeTwoObjects&lt;NonNullable&lt;T&gt;, NonNullable&lt;U&gt;&gt; | undefined           : T | U<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 <code>nullable<\/code> \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"javascript\">type A = { key1: string } type B = { key1: undefined }   const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c.key1;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/de6\/7fd\/d5e\/de67fdd5ea992ac631593f1638a279fe\" width=\"770\" height=\"179\"><figcaption><\/figcaption><\/figure>\n<h3>\u0418&#8230; \u0412\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451!<\/h3>\n<p>\u041c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u044d\u0442\u043e! \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442\u0441\u044f \u0434\u0430\u0436\u0435 \u0434\u043b\u044f <code>nullable<\/code> , \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u0448 generic \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"javascript\">type A = { key1: { a: { b: 'c'} }, key2: undefined } type B = { key1: { a: {} }, key3: string }   const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c.<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/43c\/26e\/5a3\/43c26e5a3a8382247e8884026ac1cb8f\" width=\"880\" height=\"317\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/704\/c2b\/12c\/704c2b12c640d8d2f403cda6e2851a4c\" width=\"880\" height=\"94\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3b4\/3df\/bfa\/3b43dfbfae5c302e917a125f37b176e8\" width=\"880\" height=\"86\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">\/**  * \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 2 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 T \u0438 U \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u0441 \u0438\u0445 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c\u0438  * \u043a\u043b\u044e\u0447\u0430\u043c\u0438. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 `DeepMergeTwoTypes`  *\/ type GetObjDifferentKeys&lt;T, U&gt; = Omit&lt;T, keyof U&gt; &amp; Omit&lt;U, keyof T&gt; \/**  * \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 2 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 T and U \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0438\u0445 \u043a\u043b\u044e\u0447\u0430\u043c\u0438  * \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 `DeepMergeTwoTypes`  *\/ type GetObjSameKeys&lt;T, U&gt; = Omit&lt;T | U, keyof GetObjDifferentKeys&lt;T, U&gt;&gt; type MergeTwoObjects&lt;T, U&gt; =   \/\/ \"\u043d\u0435 \u043e\u0431\u0449\u0438\u0435\" \u043a\u043b\u044e\u0447\u0438 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b   Partial&lt;GetObjDifferentKeys&lt;T, U&gt;&gt;   \/\/ \u043e\u0431\u0449\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0437\u0430 \u0441\u0447\u0451\u0442 `DeepMergeTwoTypes&lt;...&gt;`   &amp; { [K in keyof GetObjSameKeys&lt;T, U&gt;]: DeepMergeTwoTypes&lt;T[K], U[K]&gt; }  \/\/ \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 2 \u0442\u0438\u043f\u0430 export type DeepMergeTwoTypes&lt;T, U&gt; =   \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043b\u0438 \u0442\u0438\u043f\u044b \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438, \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u0442 \u0438\u0445 \u0438    \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e   [T, U] extends [(infer TItem)[], (infer UItem)[]]     ? DeepMergeTwoTypes&lt;TItem, UItem&gt;[]     \/\/ \u0435\u0441\u043b\u0438 \u0442\u0438\u043f\u044b \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b     : [T, U] extends [          { [key: string]: unknown},           { [key: string]: unknown }        ]       ? MergeTwoObjects&lt;T, U&gt;       : [T, U] extends [           { [key: string]: unknown } | undefined,            { [key: string]: unknown } | undefined          ]         ? MergeTwoObjects&lt;NonNullable&lt;T&gt;, NonNullable&lt;U&gt;&gt; | undefined           : T | U  \/\/ \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c: type A = { key1: { a: { b: 'c'} }, key2: undefined } type B = { key1: { a: {} }, key3: string }  const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c.key<\/code><\/pre>\n<h3>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0448\u0442\u0440\u0438\u0445<\/h3>\n<p>\u041a\u0430\u043a \u0431\u044b \u0442\u0430\u043a \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c&nbsp;<code>DeepMergeTwoTypes&lt;T, U&gt;<\/code>&nbsp;generic, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043c\u043e\u0433 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c&nbsp;<code>N<\/code>&nbsp;\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u0434\u0432\u0443\u0445? <\/p>\n<p>\u042f \u043e\u0441\u0442\u0430\u0432\u043b\u044e \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u043d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043c\u043e\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0447\u0435\u0440\u043d\u043e\u0432\u0438\u043a  <a href=\"https:\/\/gist.github.com\/Svehla\/2c399396cb678503990837c0c997c0db\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>).<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a61\/db6\/0a5\/a61db60a515be184eecbe4e6867bcae4\" width=\"770\" height=\"348\"><figcaption><\/figcaption><\/figure>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430<\/h4>\n<p>\u042d\u0442\u043e \u043c\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043e\u043f\u044b\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0441\u044c\u0431\u0430 \u043e\u0431 \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0430\u0445, \u0437\u0430\u043f\u044f\u0442\u044b\u0445 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u043e\u0441\u043d\u043e\u044f\u0437\u044b\u0447\u043d\u044b\u0445 \u0444\u0440\u0430\u0437\u0430\u0445 \u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u043b\u0438\u0447\u043a\u0443.<\/p>\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\/post\/526998\/\"> https:\/\/habr.com\/ru\/post\/526998\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u041f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0432 TypeScript \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 generic-\u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 key-value \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430: \u044f \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043e \u043d\u0435 \u0441\u0442\u0430\u043b \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 (\u0432\u0440\u043e\u0434\u0435 generic, key-value), \u0442.\u043a., \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430.<\/em><\/p>\n<h3>TLDR:<\/h3>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043b\u044f <code>DeepMergeTwoTypes<\/code> \u0431\u0443\u0434\u0435\u0442 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438. \u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0435\u0433\u043e \u0432 \u0432\u0430\u0448\u0443 IDE, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0441 \u043d\u0438\u043c.<\/p>\n<p>\u041a\u0430\u043a \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432 vsCode:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0443\u0432\u0435\u0440\u0435\u043d\u044b \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u043e\u0437\u043d\u0430\u043d\u0438\u044f\u0445 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 generic-\u0438 \u0432 TypeScript, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f <a href=\"https:\/\/kuba-svehla.medium.com\/minimalist-typescript-generics-173d09da66b4\" rel=\"noopener noreferrer nofollow\">\u0441 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0451\u0439<\/a> (Miniminalist Typescript &#8212; Generics)<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0435\u0433\u043e \u0432 \u0432\u0430\u0448\u0443 IDE (<em>\u043f\u0440\u0438\u043c. \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430: \u0438\u043b\u0438 \u0432 <\/em><a href=\"https:\/\/www.typescriptlang.org\/play\" rel=\"noopener noreferrer nofollow\"><em>TypeScript Playground \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0443<\/em><\/a>).<\/p>\n<h3>Disclaimer<\/h3>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043e\u0434 \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432 production \u0432\u044b \u0434\u0435\u043b\u0430\u0435\u0442\u0435 \u044d\u0442\u043e \u043d\u0430 \u0441\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u0445 \u0438 \u0440\u0438\u0441\u043a (\u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043c\u044b \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c).<\/p>\n<h3>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f &amp;-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0432 Typescript<\/h3>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0434\u0432\u0430 \u0442\u0438\u043f\u0430 <code>A<\/code> \u0438 <code>B<\/code> \u0438 \u043d\u043e\u0432\u044b\u0439 \u0442\u0438\u043f <code>C<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f <code>A &amp; B<\/code><\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: string, key3: string } type C = A &amp; B const a = (c: C) =&gt; c.<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0441\u0451 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u0432\u044b \u043d\u0435 \u043d\u0430\u0447\u043d\u0451\u0442\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: null, key3: string } type C = A &amp; B<\/code><\/pre>\n<p>\u0422\u0438\u043f <code>A<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 <code>key2<\/code> \u043a\u0430\u043a \u0441\u0442\u0440\u043e\u043a\u0443, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0432 \u0442\u0438\u043f\u0435 <code>B<\/code> \u044d\u0442\u043e <code>null<\/code>.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Typescript \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043a\u0430\u043a <code>never<\/code> \u0438 \u0442\u0438\u043f <code>C<\/code> \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0451\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u0412 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u043b\u0438 \u0447\u0435\u0433\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u044d\u0442\u043e\u0433\u043e:<\/p>\n<pre><code class=\"javascript\">type ExpectedType = {   key1: string | null,   key2: string,   key3: string }<\/code><\/pre>\n<h3>\u041f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0451\u043c \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f generic-\u0442\u0438\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u0442\u0438\u043f\u044b Typescript. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c 2 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 generic-\u0442\u0438\u043f\u0430.<\/p>\n<h4>GetObjDifferentKeys&lt;&gt;<\/h4>\n<pre><code class=\"javascript\">type GetObjDifferentKeys&lt;T, U&gt; = Omit&lt;T, keyof U&gt; &amp; Omit&lt;U, keyof T&gt;<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 2 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0438\u0437 <code>A<\/code> \u0438 <code>B<\/code>.<\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: null, key3: string }  type C = GetObjDifferentKeys&lt;A, B&gt;['']<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h4>GetObjSameKeys&lt;&gt;<\/h4>\n<p>\u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u0432\u0435\u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 generic-\u0443 \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u0434\u0440\u0443\u0433\u043e\u0439 \u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0442\u0430\u0449\u0438\u0442 \u0432\u0441\u0435 \u043a\u043b\u044e\u0447\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0441\u0442\u044c \u0432 \u043e\u0431\u043e\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u0445.<\/p>\n<pre><code class=\"javascript\">type GetObjSameKeys&lt;T, U&gt; = Omit&lt;T | U, keyof GetObjDifferentKeys&lt;T, U&gt;&gt;<\/code><\/pre>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f \u2014 \u043e\u0431\u044a\u0435\u043a\u0442.<\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: null, key3: string } type C = GetObjSameKeys&lt;A, B&gt;<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0441\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0433\u043e\u0442\u043e\u0432\u044b, \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e generic-\u0442\u0438\u043f\u0430 <code>DeepMergeTwoTypes<\/code><\/p>\n<p><code>DeepMergeTwoTypes&lt;&gt;<\/code><\/p>\n<pre><code class=\"javascript\">type DeepMergeTwoTypes&lt;T, U&gt; =   \/\/ \"\u043d\u0435 \u043e\u0431\u0449\u0438\u0435\" (\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435) \u043a\u043b\u044e\u0447\u0438 - \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b   Partial&lt;GetObjDifferentKeys&lt;T, U&gt;&gt;   \/\/ \u043e\u0431\u0449\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 - \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b   &amp; { [K in keyof GetObjSameKeys&lt;T, U&gt;]: T[K] | U[K] }<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 generic \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u0435 &#171;\u043d\u0435 \u043e\u0431\u0449\u0438\u0435&#187; \u043a\u043b\u044e\u0447\u0438 \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 <code>T<\/code> \u0438 <code>U<\/code>, \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0445 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 (\u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438). \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u044d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c\u0443 \u0442\u0438\u043f\u0443 <code>Partial&lt;&gt;<\/code>, \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Typescript. \u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u0441 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f (\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c <code>&amp;<\/code>-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430) \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u043c \u0432\u0441\u0435 \u043e\u0431\u0449\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u043c\u0435\u0436\u0434\u0443 <code>T<\/code> \u0438 <code>U<\/code> , \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 <code>T[K] | U[K]<\/code>.<\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0438\u0436\u0435. \u041d\u043e\u0432\u044b\u0439 generic \u043d\u0430\u0448\u0451\u043b &#171;\u043d\u0435-\u043e\u0431\u0449\u0438\u0435&#187; \u043a\u043b\u044e\u0447\u0438 \u0438 \u0441\u0434\u0435\u043b\u0430\u043b \u0438\u0445 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 (<code>?<\/code>), \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0441\u0442\u0440\u043e\u0433\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b.<\/p>\n<pre><code class=\"javascript\">type A = { key1: string, key2: string } type B = { key2: null, key3: string } const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c.<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u043e \u043d\u0430\u0448&nbsp;<code>DeepMergeTwoTypes<\/code>&nbsp;generic \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0441\u043e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\u043c\u0438. \u0422\u0430\u043a \u0447\u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432 \u043d\u043e\u0432\u044b\u0439 generic \u0442\u0438\u043f&nbsp;<code>MergeTwoObjects<\/code>&nbsp;\u0438 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c&nbsp;<code>DeepMergeTwoTypes<\/code>&nbsp;\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043e\u043d \u043d\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442 \u0432\u0441\u0435 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<pre><code class=\"javascript\">\/\/ \u044d\u0442\u043e\u0442 generic \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 DeepMergeTwoTypes&lt;&gt; type MergeTwoObjects&lt;T, U&gt; =   \/\/ \"\u043d\u0435 \u043e\u0431\u0449\u0438\u0435\" (\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435) \u043a\u043b\u044e\u0447\u0438 - \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b   Partial&lt;GetObjDifferentKeys&lt;T, U&gt;&gt;   \/\/ \u043e\u0431\u0449\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 - \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b   &amp; {[K in keyof GetObjSameKeys&lt;T, U&gt;]: DeepMergeTwoTypes&lt;T[K], U[K]&gt;}  export type DeepMergeTwoTypes&lt;T, U&gt; =   \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043b\u0438 \u0442\u0438\u043f\u044b \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438, \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e   [T, U] extends [{ [key: string]: unknown }, { [key: string]: unknown } ]     ? MergeTwoObjects&lt;T, U&gt;     : T | U<\/code><\/pre>\n<p><strong><em>PRO TIP<\/em><\/strong><em>: \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 DeepMergeTwoTypes \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f if-else \u0443\u0441\u043b\u043e\u0432\u0438\u0435 (<\/em><code>extends ?:<\/code>)<em> \u041c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0447\u0442\u043e \u0438 <\/em><code>T<\/code> \u0438 <code>U<\/code> \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u044e\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u044e, \u0437\u0430\u0441\u0443\u043d\u0443\u0432 \u0438\u0445 \u0432 \u043a\u043e\u0440\u0442\u0435\u0436 (tuple) <code>[T, U]<\/code>. \u042d\u0442\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 <code>&amp;&amp;<\/code>-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0432 Javascript.<\/p>\n<p>\u042d\u0442\u043e\u0442 generic \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u043e\u0431\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0438\u043f\u0443&nbsp;<code>{ [key: string]: unknown }<\/code>&nbsp;(\u044d\u0442\u043e&nbsp;<code>Object<\/code>). \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0442\u0430\u043a, \u0442\u043e \u043e\u043d \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0438\u0445 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c&nbsp;<code>MergeTwoObject&lt;&gt;<\/code>. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430: \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 <\/em><code>extends { [key: string]: unknown }<\/code><em> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0435-\u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0442.\u0435. \u0441\u0442\u0440\u043e\u043a\u0438, \u0447\u0438\u0441\u043b\u0430, booleans \u0438 \u0442.\u0434.. <\/em><\/p>\n<p>\u0418 \u0432\u0443\u0430\u043b\u044f! \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 generic \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0451\u043d \u043a\u043e \u0432\u0441\u0435\u043c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c. \u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"javascript\">type A = { key: { a: null, c: string} } type B = { key: { a: string, b: string} } const fn = (c: MergeTwoObjects&lt;A, B&gt;) =&gt; c.key.<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0451?<\/p>\n<p>\u0423\u0432\u044b, \u043d\u0435\u0442. \u041d\u0430\u0448 \u043d\u043e\u0432\u044b\u0439 generic \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043c\u0430\u0441\u0441\u0438\u0432\u044b.<\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435, \u0447\u0435\u043c \u043c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e <code>infer<\/code> (to infer &#8212; \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c).<\/p>\n<p><code>infer<\/code>&nbsp;\u0441\u043c\u043e\u0442\u0440\u0438\u0442 \u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u0442 \u0435\u0451 \u0442\u0438\u043f (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432). \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u043e&nbsp;<code>infer<\/code>&nbsp;\u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/release-notes\/typescript-2-8.html#type-inference-in-conditional-types\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a> (Type inference in conditional types).<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <code>infer<\/code>. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0438\u043f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0432\u0437\u044f\u0442\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 (<code>Item<\/code>):<\/p>\n<pre><code class=\"javascript\">export type ArrayElement&lt;A&gt; = A extends (infer T)[] ? T : never  \/\/ Item === (number | string) type Item = ArrayElement&lt;(number | string)[]&gt;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u044d\u0442\u0438 \u0434\u0432\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u0442\u0438\u043f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0430. \u0418 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c&nbsp;<code>DeepMergeTwoTypes<\/code>&nbsp;\u0434\u043b\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432.<\/p>\n<pre><code class=\"javascript\">export type DeepMergeTwoTypes&lt;T, U&gt; =   \/\/ ----- 2 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 ------   \/\/ \u044d\u0442\u0430 \u23ec   [T, U] extends [(infer TItem)[], (infer UItem)[]]     \/\/ ... \u0438 \u044d\u0442\u0430 \u23ec     ? DeepMergeTwoTypes&lt;TItem, UItem&gt;[]     : ... rest of previous generic ...<\/code><\/pre>\n<p> \u0421\u0435\u0439\u0447\u0430\u0441 <code>DeepMergeTwoTypes<\/code> \u043c\u043e\u0436\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0430\u043c \u0441\u0435\u0431\u044f, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u044b.<\/p>\n<pre><code class=\"javascript\">type A = [{ key1: string, key2: string }] type B = [{ key2: null, key3: string }] const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c[0].<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0418 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442! \u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0451?<\/p>\n<p>\u042d\u0445&#8230; \u041d\u0435\u0442. \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 <code>Nullable<\/code> \u0442\u0438\u043f\u043e\u0432 \u0441 <code>non-nullable<\/code>. <\/p>\n<pre><code class=\"javascript\">type A = { key1: string } type B = { key1: undefined }  type C = DeepMergeTwoTypes&lt;A, B&gt;['key']<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f \u2014 <code>string | undefined<\/code>, \u043d\u043e \u043d\u0430 \u0434\u0435\u043b\u0435 \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0451 \u0434\u0432\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u043d\u0430\u0448\u0443 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 <code>if-else<\/code> .<\/p>\n<pre><code class=\"javascript\">export type DeepMergeTwoTypes&lt;T, U&gt; =   [T, U] extends [(infer TItem)[], (infer UItem)[]]     ? DeepMergeTwoTypes&lt;TItem, UItem&gt;[]     : [T, U] extends [{ [key: string]: unknown}, { [key: string]: unknown } ]       ? MergeTwoObjects&lt;T, U&gt;       \/\/ ----- 2 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 ------       \/\/ \u044d\u0442\u0430 \u23ec       : [T, U] extends [           { [key: string]: unknown } | undefined,            { [key: string]: unknown } | undefined          ]         \/\/ ... \u0438 \u044d\u0442\u0430 \u23ec         ? MergeTwoObjects&lt;NonNullable&lt;T&gt;, NonNullable&lt;U&gt;&gt; | undefined           : T | U<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 <code>nullable<\/code> \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"javascript\">type A = { key1: string } type B = { key1: undefined }   const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c.key1;<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u0418&#8230; \u0412\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451!<\/h3>\n<p>\u041c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u044d\u0442\u043e! \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442\u0441\u044f \u0434\u0430\u0436\u0435 \u0434\u043b\u044f <code>nullable<\/code> , \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u0448 generic \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"javascript\">type A = { key1: { a: { b: 'c'} }, key2: undefined } type B = { key1: { a: {} }, key3: string }   const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c.<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">\/**  * \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 2 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 T \u0438 U \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u0441 \u0438\u0445 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c\u0438  * \u043a\u043b\u044e\u0447\u0430\u043c\u0438. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 `DeepMergeTwoTypes`  *\/ type GetObjDifferentKeys&lt;T, U&gt; = Omit&lt;T, keyof U&gt; &amp; Omit&lt;U, keyof T&gt; \/**  * \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 2 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 T and U \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0438\u0445 \u043a\u043b\u044e\u0447\u0430\u043c\u0438  * \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 `DeepMergeTwoTypes`  *\/ type GetObjSameKeys&lt;T, U&gt; = Omit&lt;T | U, keyof GetObjDifferentKeys&lt;T, U&gt;&gt; type MergeTwoObjects&lt;T, U&gt; =   \/\/ \"\u043d\u0435 \u043e\u0431\u0449\u0438\u0435\" \u043a\u043b\u044e\u0447\u0438 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b   Partial&lt;GetObjDifferentKeys&lt;T, U&gt;&gt;   \/\/ \u043e\u0431\u0449\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0437\u0430 \u0441\u0447\u0451\u0442 `DeepMergeTwoTypes&lt;...&gt;`   &amp; { [K in keyof GetObjSameKeys&lt;T, U&gt;]: DeepMergeTwoTypes&lt;T[K], U[K]&gt; }  \/\/ \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 2 \u0442\u0438\u043f\u0430 export type DeepMergeTwoTypes&lt;T, U&gt; =   \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043b\u0438 \u0442\u0438\u043f\u044b \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438, \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u0442 \u0438\u0445 \u0438    \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e   [T, U] extends [(infer TItem)[], (infer UItem)[]]     ? DeepMergeTwoTypes&lt;TItem, UItem&gt;[]     \/\/ \u0435\u0441\u043b\u0438 \u0442\u0438\u043f\u044b \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b     : [T, U] extends [          { [key: string]: unknown},           { [key: string]: unknown }        ]       ? MergeTwoObjects&lt;T, U&gt;       : [T, U] extends [           { [key: string]: unknown } | undefined,            { [key: string]: unknown } | undefined          ]         ? MergeTwoObjects&lt;NonNullable&lt;T&gt;, NonNullable&lt;U&gt;&gt; | undefined           : T | U  \/\/ \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c: type A = { key1: { a: { b: 'c'} }, key2: undefined } type B = { key1: { a: {} }, key3: string }  const fn = (c: DeepMergeTwoTypes&lt;A, B&gt;) =&gt; c.key<\/code><\/pre>\n<h3>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0448\u0442\u0440\u0438\u0445<\/h3>\n<p>\u041a\u0430\u043a \u0431\u044b \u0442\u0430\u043a \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c&nbsp;<code>DeepMergeTwoTypes&lt;T, U&gt;<\/code>&nbsp;generic, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043c\u043e\u0433 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c&nbsp;<code>N<\/code>&nbsp;\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u0434\u0432\u0443\u0445? <\/p>\n<p>\u042f \u043e\u0441\u0442\u0430\u0432\u043b\u044e \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u043d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043c\u043e\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0447\u0435\u0440\u043d\u043e\u0432\u0438\u043a  <a href=\"https:\/\/gist.github.com\/Svehla\/2c399396cb678503990837c0c997c0db\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>).<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430<\/h4>\n<p>\u042d\u0442\u043e \u043c\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043e\u043f\u044b\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0441\u044c\u0431\u0430 \u043e\u0431 \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0430\u0445, \u0437\u0430\u043f\u044f\u0442\u044b\u0445 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u043e\u0441\u043d\u043e\u044f\u0437\u044b\u0447\u043d\u044b\u0445 \u0444\u0440\u0430\u0437\u0430\u0445 \u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u043b\u0438\u0447\u043a\u0443.<\/p>\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\/post\/526998\/\"> https:\/\/habr.com\/ru\/post\/526998\/<\/a><br \/><\/br><\/br><\/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-312761","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/312761","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=312761"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/312761\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=312761"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=312761"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=312761"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}