В чем преимущество использования '--strictFunctionTypes' в Typescript?
Как я понимаю, --strictFunctionTypes
Опция компилятора в Typescript предотвращает работу очень распространенного варианта использования полиморфизма:
type Handler = (request: Request) => Response
const myHandler: Handler = (request: Request & { extraArg: boolean }) => {
return !!request.extraArg
}
Как правило, я предполагаю, что все параметры компилятора в strict
у семьи есть некоторые большие преимущества, но в этом случае я вижу только то, что это мешает очень логичному поведению работать.
Так в каких случаях этот вариант действительно дает некоторые преимущества? Какие вредные сценарии это предотвращает?
1 ответ
На самом деле очень легко вызвать ошибку во время выполнения без strictFunctionTypes
,
Давайте рассмотрим следующий пример:
type Handler = (request: Request) => Response
const myHandler: Handler = (request: Request & { extraArg: string }) => {
// extraArg is required so need to check for null
request.extraArg.toUpperCase();
return null as any;
}
declare let r: Request; // comes from sowhere
myHandler(r); // no need to pass in the extraArg not required by the signature
Так что в приведенном выше примере сигнатура функции требует Response
так что это все, что мы должны пройти в Response
, Но реализация рассчитывает получить Request & { extraArg: string }
в котором extraArg
требуется, и получить доступ к нему без необходимости проверки (в конце концов, если это требуется, вызываемый должен был передать его).
Это вид ошибок strictFunctionTypes
предотвращает. Если аргумент в сигнатуре имеет базовый тип, в то время как реализация ожидает производный тип, нет гарантии, что реализация получит производный тип, поскольку подпись требует только передачи базового типа в
Эта опция исправляет, на мой взгляд, ошибку в компиляторе TypeScript. Если это не ошибка, то это просто плохое дизайнерское решение, и появление новой опции компилятора подтверждает мою точку зрения. Начнем с примера, по умолчанию следующий код будет скомпилирован без проблем:
// Focus all your attention on callback signature
// It has date parameter which is a union type
function getCurrentYear(callback: (date: string | number) => void) {
callback((Math.random() > 0.5) ? '2020' : 2020);
}
// note that we ignored the fact that in 50% cases our callback returns string type instead of number.
getCurrentYear((date: string) => {
console.log(date.charAt(0)); // in 50% it is RUNTIME ERROR
});
Таким образом, эта стрелочная функция, переданная в getCurrentYear, сужает тип параметра "дата", и TypeScript это не касается. Однако тот же трюк в другом контексте с переменными даже без какого-либо строгого правила приведет к ошибке:
let x: string | number = (Math.random() > 0.5) ? '2020' : 2020;
const y: number = x; // COMPILE TIME ERROR
Это имеет гораздо больше смысла, и включение --strictFunctionTypes попросит компилятор следовать тому же поведению в функциях обратного вызова. Это определенно поможет вам предотвратить некоторые ошибки в большом проекте.
Источник: