Вероятно, это отсутствующая функция.
Когда вы проверяете (x === "A")
, он действует как защита типа для типа значения x
, вызывая его сужение от объединения. введите от "A"|"B"
до "A"
через анализ потока управления .
К сожалению, общие параметры типа c в TypeScript не сужаются при анализе потока управления; см. microsoft / TypeScript # 13995 для получения дополнительной информации. Так, например, проверка (key === "A")
будет не сужать тип K
до "A"
. Такое ограничение имеет смысл, когда у вас есть несколько значений одного типа c generi:
function foo<K extends Union>(key: K, x: Union, key2: K) {
if (key2 === "A") {
Global[key].toFixed(); // error!
}
}
Очевидно, что проверка значения key2
не должна влиять на тип key
, поэтому консерватор не считает, что K
следует сузить. Это основная проблема c в microsoft / TypeScript # 13995, и были подняты многочисленные связанные с этим вопросы с предложениями о том, как ее решить в тех случаях, когда такое сужение безопасно выполнять. Пока что до сих пор ничего не дошло до языка.
Хотя это не совсем полная история; можно противостоять: хорошо, возможно вы не можете сузить параметр типа K
с K extends Union
до K extends "A"
, но , конечно, вы можете сузить тип значения key
с K
до "A"
или K & "A"
( тип пересечения ), что сделает Global[key].toFixed()
успешным:
if (key === "A") {
Global[key as (K & "A")].toFixed(); // okay
}
И сейчас у меня нет хорошего ответа на этот вопрос. Большинство вопросов, которые я видел об этом, в конечном итоге были переданы на microsoft / TypeScript # 13995. 10
Наиболее полный ответ, который я могу получить, - это то, что использование встроенных защитных устройств типа a === b
или typeof a === "string"
или a instanceof B
или a in b
приводит только к фильтрации союзов или, возможно, сужение string
или number
до строковых или числовых литералов, но никогда не создает тип пересечения. Я спрашивал ранее, см. Microsoft / TypeScript # 21732, для защиты типа a in b
для создания некоторых пересечений, но она не была реализована. Таким образом, это может быть две отсутствующие функции:
- без сужающихся обобщенных параметров типа c и
- без встроенного ограждения типа, сужающегося до пересечений.
Итак, обходные пути: Очевидно, что самый простой способ для этого примера - просто переназначить значение переменной типового типа c в переменную типа объединения:
const k: Union = key;
if (k === "A") {
Global[k].toFixed();
}
Или вы можете использовать утверждение типа , как указано выше as (K & "A")
или просто as "A"
:
if (key === "A") {
Global[key as (K & "A")].toFixed(); // okay
Global[key as "A"].toFixed(); // okay
}
Или, если это часто случается, вы можете написать свой собственный функция защиты определенного пользователем типа функция, поскольку защита определенного пользователем типа do создает пересечения в ветви true
следующего потока управления:
const isEq =
<T extends string | number | boolean>(v: any, c: T): v is T => v === c;
if (isEq(key, "A")) {
Global[key].toFixed(); // okay, key is now of type K & "A";
}
Hope один из тех, кто помогает вам. Хорошо, удачи!
Детская площадка ссылка на код