Логический вывод типа в TypeScript¶
TypeScript может логически вывести (а затем проверить) тип переменной на основе нескольких простых правил. Потому как эти правила просты, вы можете научить свой мозг распознавать безопасный / небезопасный код (это случилось со мной и моими товарищами по команде довольно быстро).
Поток типов - это то, как я представляю себе в уме распространение информации о типах.
Определение переменной¶
Типы переменной определяются по её определению.
1 2 3 |
|
Это пример типов, распространяющихся справа налево.
Типы значений возвращаемых функцией¶
Тип возвращаемого значения определяется инструкцией возврата, например, предполагается, что следующая функция возвращает число
.
1 2 3 |
|
Это пример типов, распространяющихся снизу вверх.
Присвоение¶
Тип параметров функции / возвращаемых значений также может быть определен посредством присваивания, например, здесь мы говорим, что foo
является сумматором
, и это делает a
и b
типом число
.
1 2 |
|
Этот факт может быть продемонстрирован с помощью приведенного ниже кода, который вызывает ошибку, как можно было и ожидать:
1 2 3 4 5 |
|
Это пример типов, распространяющихся слева направо.
Логический вывод типов срабатывает с этим же стилем присвоения, если вы создаете функцию с параметром в виде колбэка. В конце концов, argument -> parameter
- это просто еще одна форма присвоения переменных.
1 2 3 4 5 6 7 8 |
|
Структурирование¶
Эти простые правила также работают при использовании структурирования (создание литерала объекта). Например, в следующем случае тип foo
определяется как {a:number, b:number}
1 2 3 4 5 |
|
Аналогично для массивов:
1 2 |
|
Ну и конечно же любое вложение:
1 2 3 4 |
|
Деструктуризация¶
И, конечно же, они также работают с деструктуризацией, оба:
1 2 3 4 5 6 |
|
и массивы:
1 2 3 |
|
И если параметр функции может быть логически выведен, то могут и его деструктурированные свойства. Например, здесь мы деструктурируем параметр на a
/b
.
1 2 3 4 5 6 7 8 9 |
|
Защита типа¶
Мы уже видели, как Защита типа помогает изменять и уточнять типы (особенно в случае объединений). Защиты типов - это просто еще одна форма логического вывода типа для переменной в блоке.
Предупреждения¶
Будьте осторожны с параметрами¶
Типы не распространяются в параметры функции, если они не могут быть логически выведены из присвоения. Например, в следующем случае компилятор не знает тип foo
, поэтому он не может определить тип a
или b
.
1 2 3 |
|
Однако, если был введен foo
, тип параметров функции может быть логически выведен (a
,b
оба выведены как имеющие тип number
в примере ниже).
1 2 3 4 |
|
Будьте осторожны с возвращаемыми значениями¶
Хотя TypeScript может обычно логически выводить тип возвращаемого значения функции, он может не соответствовать ожидаемому. Например, здесь функция foo
имеет тип возврата any
.
1 2 3 4 5 6 7 |
|
Это связано с тем, что на возвращаемый тип влияет плохое определение типа для addOne
(c
равно any
, поэтому возвращаемое от addIn
равно any
, поэтому отсюда и foo
равно any
).
Я считаю, что проще всего всегда быть явным в описании возвращаемых значений функций. Ведь эти описания являются теоремой, а тело функции является доказательством.
Есть и другие случаи, которые нетрудно себе представить, но хорошая новость заключается в том, что есть флаг компилятора, который может помочь отловить такие ошибки.
noImplicitAny
¶
Флаг noImplicitAny
указывает компилятору выдавать ошибку, если он не может определить тип переменной (и, следовательно, может иметь ее только как неявный any
тип). Далее вы сможете
- либо сказать, что да, я хочу, чтобы это было типом
any
и явно добавить описание типа: any
- либо помочь компилятору, добавив еще несколько правильных описаний.