В чем преимущество использования '--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 попросит компилятор следовать тому же поведению в функциях обратного вызова. Это определенно поможет вам предотвратить некоторые ошибки в большом проекте.

Источник:

https://medium.com/javascript-in-plain-english/what-are-these-strict-compiler-options-in-typescript-part-2-a7e974b13e54

Другие вопросы по тегам