| 
1 |  | -# Type Inference in TypeScript  | 
 | 1 | +# Логический вывод типа в TypeScript  | 
2 | 2 | 
 
  | 
3 |  | -TypeScript can infer (and then check) the type of a variable based on a few simple rules. Because these rules  | 
4 |  | -are simple you can train your brain to recognize safe / unsafe code (it happened for me and my teammates quite quickly).  | 
 | 3 | +TypeScript может логически вывести (а затем проверить) тип переменной на основе нескольких простых правил. Потому как эти правила просты, вы можете научить свой мозг распознавать безопасный / небезопасный код (это случилось со мной и моими товарищами по команде довольно быстро).  | 
5 | 4 | 
 
  | 
6 |  | -> The types flowing is just how I imagine in my brain the flow of type information.  | 
 | 5 | +> Поток типов - это то, как я представляю себе в уме распространение информации о типах.  | 
7 | 6 | 
  | 
8 |  | -## Variable Definition  | 
 | 7 | +## Определение переменной  | 
9 | 8 | 
 
  | 
10 |  | -Types of a variable are inferred by definition.  | 
 | 9 | +Типы переменной определяются по её определению.  | 
11 | 10 | 
 
  | 
12 | 11 | ```ts  | 
13 |  | -let foo = 123; // foo is a `number`  | 
14 |  | -let bar = "Hello"; // bar is a `string`  | 
15 |  | -foo = bar; // Error: cannot assign `string` to a `number`  | 
 | 12 | +let foo = 123; // foo `число`  | 
 | 13 | +let bar = "Hello"; // bar `строка`  | 
 | 14 | +foo = bar; // Ошибка: невозможно `строке` присвоить `число`  | 
16 | 15 | ```  | 
17 | 16 | 
 
  | 
18 |  | -This is an example of types flowing from right to left.  | 
 | 17 | +Это пример типов, распространяющихся справа налево.  | 
19 | 18 | 
 
  | 
20 |  | -## Function Return Types  | 
 | 19 | +## Типы значений возвращаемых функцией  | 
21 | 20 | 
 
  | 
22 |  | -The return type is inferred by the return statements e.g. the following function is inferred to return a `number`.  | 
 | 21 | +Тип возвращаемого значения определяется инструкцией возврата, например, предполагается, что следующая функция возвращает `число`.  | 
23 | 22 | 
 
  | 
24 | 23 | ```ts  | 
25 | 24 | function add(a: number, b: number) {  | 
26 | 25 |  return a + b;  | 
27 | 26 | }  | 
28 | 27 | ```  | 
29 | 28 | 
 
  | 
30 |  | -This is an example of types flowing bottom out.  | 
 | 29 | +Это пример типов, распространяющихся снизу вверх.  | 
31 | 30 | 
 
  | 
32 |  | -## Assignment  | 
 | 31 | +## Присвоение  | 
33 | 32 | 
 
  | 
34 |  | -The type of function parameters / return values can also be inferred by assignment e.g. here we say that `foo` is an `Adder`, that makes `number` the type of `a` and `b`.  | 
 | 33 | +Тип параметров функции / возвращаемых значений также может быть определен посредством присваивания, например, здесь мы говорим, что `foo` является `сумматором`, и это делает `a` и `b` типом `число`.  | 
35 | 34 | 
 
  | 
36 | 35 | ```ts  | 
37 | 36 | type Adder = (a: number, b: number) => number;  | 
38 | 37 | let foo: Adder = (a, b) => a + b;  | 
39 | 38 | ```  | 
40 | 39 | 
 
  | 
41 |  | -This fact can be demonstrated by the below code which raises an error as you would hope:  | 
 | 40 | +Этот факт может быть продемонстрирован с помощью приведенного ниже кода, который вызывает ошибку, как можно было и ожидать:  | 
42 | 41 | 
 
  | 
43 | 42 | ```ts  | 
44 | 43 | type Adder = (a: number, b: number) => number;  | 
45 | 44 | let foo: Adder = (a, b) => {  | 
46 |  | - a = "hello"; // Error: cannot assign `string` to a `number`  | 
 | 45 | + a = "hello"; // Ошибка: невозможно `строке` присвоить `число`  | 
47 | 46 |  return a + b;  | 
48 | 47 | }  | 
49 | 48 | ```  | 
50 | 49 | 
 
  | 
51 |  | -This is an example of types flowing from left to right.  | 
 | 50 | +Это пример типов, распространяющихся слева направо.  | 
52 | 51 | 
 
  | 
53 |  | -The same *assignment* style type inference works if you create a function for a callback argument. After all an `argument -> parameter`is just another form of variable assignment.  | 
 | 52 | +Логический вывод типов срабатывает с этим же стилем присвоения, если вы создаете функцию с параметром в виде колбэка. В конце концов, `argument -> parameter` - это просто еще одна форма присвоения переменных.  | 
54 | 53 | 
 
  | 
55 | 54 | ```ts  | 
56 | 55 | type Adder = (a: number, b: number) => number;  | 
57 | 56 | function iTakeAnAdder(adder: Adder) {  | 
58 | 57 |  return adder(1, 2);  | 
59 | 58 | }  | 
60 | 59 | iTakeAnAdder((a, b) => {  | 
61 |  | - // a = "hello"; // Would Error: cannot assign `string` to a `number`  | 
 | 60 | + // a = "hello"; // Будет ошибка: невозможно `строке` присвоить `число`  | 
62 | 61 |  return a + b;  | 
63 | 62 | })  | 
64 | 63 | ```  | 
65 | 64 | 
 
  | 
66 |  | -## Structuring  | 
 | 65 | +## Структурирование  | 
67 | 66 | 
 
  | 
68 |  | -These simple rules also work in the presence of **structuring** (object literal creation). For example in the following case the type of `foo` is inferred to be `{a:number, b:number}`  | 
 | 67 | +Эти простые правила также работают при использовании **структурирования** (создание литерала объекта). Например, в следующем случае тип `foo` определяется как `{a:number, b:number}`  | 
69 | 68 | 
 
  | 
70 | 69 | ```ts  | 
71 | 70 | let foo = {  | 
72 | 71 |  a: 123,  | 
73 | 72 |  b: 456  | 
74 | 73 | };  | 
75 |  | -// foo.a = "hello"; // Would Error: cannot assign `string` to a `number`  | 
 | 74 | +// foo.a = "hello"; // Будет ошибка: невозможно `строке` присвоить `число`  | 
76 | 75 | ```  | 
77 | 76 | 
 
  | 
78 |  | -Similarly for arrays:  | 
 | 77 | +Аналогично для массивов:  | 
79 | 78 | 
 
  | 
80 | 79 | ```ts  | 
81 | 80 | const bar = [1,2,3];  | 
82 |  | -// bar[0] = "hello"; // Would error: cannot assign `string` to a `number`  | 
 | 81 | +// bar[0] = "hello"; // Будет ошибка: невозможно `строке` присвоить `число`  | 
83 | 82 | ```  | 
84 | 83 | 
 
  | 
85 |  | -And of course any nesting:  | 
 | 84 | +Ну и конечно же любое вложение:  | 
86 | 85 | 
 
  | 
87 | 86 | ```ts  | 
88 | 87 | let foo = {  | 
89 | 88 |  bar: [1, 3, 4]  | 
90 | 89 | };  | 
91 |  | -// foo.bar[0] = 'hello'; // Would error: cannot assign `string` to a `number`  | 
 | 90 | +// foo.bar[0] = 'hello'; // Будет ошибка: невозможно `строке` присвоить `число`  | 
92 | 91 | ```  | 
93 | 92 | 
 
  | 
94 |  | -## Destructuring  | 
 | 93 | +## Деструктуризация  | 
95 | 94 | 
 
  | 
96 |  | -And of course, they also work with destructuring, both objects:  | 
 | 95 | +И, конечно же, они также работают с деструктуризацией, оба:  | 
97 | 96 | 
 
  | 
98 | 97 | ```ts  | 
99 | 98 | let foo = {  | 
100 | 99 |  a: 123,  | 
101 | 100 |  b: 456  | 
102 | 101 | };  | 
103 | 102 | let {a} = foo;  | 
104 |  | -// a = "hello"; // Would Error: cannot assign `string` to a `number`  | 
 | 103 | +// a = "hello"; // Будет ошибка: невозможно `строке` присвоить `число`  | 
105 | 104 | ```  | 
106 | 105 | 
 
  | 
107 |  | -and arrays:  | 
 | 106 | +и массивы:  | 
108 | 107 | 
 
  | 
109 | 108 | ```ts  | 
110 | 109 | const bar = [1, 2];  | 
111 | 110 | let [a, b] = bar;  | 
112 |  | -// a = "hello"; // Would Error: cannot assign `string` to a `number`  | 
 | 111 | +// a = "hello"; // Будет ошибка: невозможно `строке` присвоить `число`  | 
113 | 112 | ```  | 
114 | 113 | 
 
  | 
115 |  | -And if the function parameter can be inferred, so can its destructured properties. For example here we destructure the argument into its `a`/`b` members.  | 
 | 114 | +И если параметр функции может быть логически выведен, то могут и его деструктурированные свойства. Например, здесь мы деструктурируем параметр на `a`/`b`.  | 
116 | 115 | 
 
  | 
117 | 116 | ```ts  | 
118 | 117 | type Adder = (numbers: { a: number, b: number }) => number;  | 
119 | 118 | function iTakeAnAdder(adder: Adder) {  | 
120 | 119 |  return adder({ a: 1, b: 2 });  | 
121 | 120 | }  | 
122 |  | -iTakeAnAdder(({a, b}) => { // Types of `a` and `b` are inferred  | 
123 |  | - // a = "hello"; // Would Error: cannot assign `string` to a `number`  | 
 | 121 | +iTakeAnAdder(({a, b}) => { // Типы `a` и` b` логически выводятся  | 
 | 122 | + // a = "hello"; // Будет ошибка: невозможно `строке` присвоить `число`  | 
124 | 123 |  return a + b;  | 
125 | 124 | })  | 
126 | 125 | ```  | 
127 | 126 | 
 
  | 
128 |  | -## Type Guards  | 
 | 127 | +## Защита типа  | 
129 | 128 | 
 
  | 
130 |  | -We have already seen how [Type Guards](./typeGuard.md) help change and narrow down types (particularly in the case of unions). Type guards are just another form of type inference for a variable in a block.  | 
 | 129 | +Мы уже видели, как [Защита типа](./typeGuard.md) помогает изменять и уточнять типы (особенно в случае объединений). Защиты типов - это просто еще одна форма логического вывода типа для переменной в блоке.  | 
131 | 130 | 
 
  | 
132 |  | -## Warnings  | 
 | 131 | +## Предупреждения  | 
133 | 132 | 
 
  | 
134 |  | -### Be careful around parameters  | 
 | 133 | +### Будьте осторожны с параметрами  | 
135 | 134 | 
 
  | 
136 |  | -Types do not flow into the function parameters if it cannot be inferred from an assignment. For example in the following case the compiler does not know the type of `foo` so it cannot infer the type of `a` or `b`.  | 
 | 135 | +Типы не распространяются в параметры функции, если они не могут быть логически выведены из присвоения. Например, в следующем случае компилятор не знает тип `foo`, поэтому он не может определить тип `a` или `b`.  | 
137 | 136 | 
 
  | 
138 | 137 | ```ts  | 
139 |  | -const foo = (a,b) => { /* do something */ };  | 
 | 138 | +const foo = (a,b) => { /* сделать что-нибудь */ };  | 
140 | 139 | ```  | 
141 | 140 | 
 
  | 
142 |  | -However, if `foo` was typed the function parameters type can be inferred (`a`,`b` are both inferred to be of type `number` in the example below).  | 
 | 141 | +Однако, если был введен `foo`, тип параметров функции может быть логически выведен (`a`,`b` оба выведены как имеющие тип `number` в примере ниже).  | 
143 | 142 | 
 
  | 
144 | 143 | ```ts  | 
145 | 144 | type TwoNumberFunction = (a: number, b: number) => void;  | 
146 |  | -const foo: TwoNumberFunction = (a, b) => { /* do something */ };  | 
 | 145 | +const foo: TwoNumberFunction = (a, b) => { /* сделать что-нибудь */ };  | 
147 | 146 | ```  | 
148 | 147 | 
 
  | 
149 |  | -### Be careful around return  | 
 | 148 | +### Будьте осторожны с возвращаемыми значениями  | 
150 | 149 | 
 
  | 
151 |  | -Although TypeScript can generally infer the return type of a function, it might not be what you expect. For example here function `foo` has a return type of `any`.  | 
 | 150 | +Хотя TypeScript может обычно логически выводить тип возвращаемого значения функции, он может не соответствовать ожидаемому. Например, здесь функция `foo` имеет тип возврата `any`.  | 
152 | 151 | 
 
  | 
153 | 152 | ```ts  | 
154 | 153 | function foo(a: number, b: number) {  | 
155 | 154 |  return a + addOne(b);  | 
156 | 155 | }  | 
157 |  | -// Some external function in a library someone wrote in JavaScript  | 
158 |  | -function addOne(a) {  | 
159 |  | - return a + 1;  | 
 | 156 | +// Какая-то внешняя функция в библиотеке, которую кто-то написал в JavaScript  | 
 | 157 | +function addOne(c) {  | 
 | 158 | + return c + 1;  | 
160 | 159 | }  | 
161 | 160 | ```  | 
162 | 161 | 
 
  | 
163 |  | -This is because the return type is impacted by the poor type definition for `addOne` (`a` is `any` so the return of `addOne` is `any` so the return of `foo` is `any`).  | 
 | 162 | +Это связано с тем, что на возвращаемый тип влияет плохое определение типа для `addOne` (`c` равно `any`, поэтому возвращаемое от `addIn` равно `any`, поэтому отсюда и `foo` равно `any`).  | 
164 | 163 | 
 
  | 
165 |  | -> I find it simplest to always be explicit about function returns. After all, these annotations are a theorem and the function body is the proof.  | 
 | 164 | +> Я считаю, что проще всего всегда быть явным в описании возвращаемых значений функций. Ведь эти описания являются теоремой, а тело функции является доказательством.  | 
166 | 165 | 
  | 
167 |  | -There are other cases that one can imagine, but the good news is that there is a compiler flag that can help catch such bugs.  | 
 | 166 | +Есть и другие случаи, которые нетрудно себе представить, но хорошая новость заключается в том, что есть флаг компилятора, который может помочь отловить такие ошибки.  | 
168 | 167 | 
 
  | 
169 | 168 | ## `noImplicitAny`  | 
170 | 169 | 
 
  | 
171 |  | -The flag `noImplicitAny` instructs the compiler to raise an error if it cannot infer the type of a variable (and therefore can only have it as an *implicit* `any` type). You can then  | 
 | 170 | +Флаг `noImplicitAny` указывает компилятору выдавать ошибку, если он не может определить тип переменной (и, следовательно, может иметь ее только как *неявный* `any` тип). Далее вы сможете  | 
172 | 171 | 
 
  | 
173 |  | -* either say that *yes I want it to be of type `any`* by *explicitly* adding an `: any` type annotation  | 
174 |  | -* help the compiler out by adding a few more *correct* annotations.  | 
 | 172 | +* либо сказать, что *да, я хочу, чтобы это было типом `any`* и *явно* добавить описание типа `: any`  | 
 | 173 | +* либо помочь компилятору, добавив еще несколько *правильных* описаний.  | 
0 commit comments