Логический вывод типа в 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 - либо помочь компилятору, добавив еще несколько правильных описаний.