Здесь происходит несколько вещей.Одна из них заключается в том, что TypeScript не понимает, что Object.values(x).includes(y)
- это защита типа на y
.Он не соответствует встроенным способам, которые компилятор пытается сузить, например, проверкам typeof
, instanceof
или in
.Чтобы помочь компилятору, вы можете использовать определяемый пользователем тип защиты , чтобы выразить этот способ проверки:
function isPropertyValue<T>(object: T, possibleValue: any): possibleValue is T[keyof T] {
return Object.values(object).includes(possibleValue);
}
declare function onlyAcceptAllowedValues(allowedValue: AllowedValues): void;
declare const v: string;
if (isPropertyValue(AllowedValues, v)) {
onlyAcceptAllowedValues(v); // v is narrowed to AllowedValues; it works!
}
Итак, давайте сначала изменим вашу функцию следующим образом:
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
if (!(isPropertyValue(AllowedValues, value)))
value = AllowedValues.LOREM_IPSUM;
// TypeScript/Intellisense still thinks it is `string`
console.log(value);
}
Ой, все еще не работает.
Второе, что происходит: если вы переназначаете значение переменной, TypeScript, по сути, разочаровывается в ее сужении.Компилятор прилагает значительные усилия, чтобы понять влияние потока управления на типы переменных, но не идеально .Итак, хотя мы понимаем, что присвоение AllowedValues.LOREM_IPSUM
value
делает его AllowedValues
, компилятор отказывается от и предполагает, что это его исходный аннотированный тип, которыйstring
.
Способ работы с этим состоит в создании новой переменной, которая, как понимает компилятор, никогда не будет ничем иным, как AllowedValues
.Самый простой способ сделать это - сделать ее переменной const
, например:
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
const allowedValue = isPropertyValue(AllowedValues, value) ? value : AllowedValues.LOREM_IPSUM;
console.log(allowedValue);
}
В приведенном выше примере новая переменная allowedValue
выводится как AllowedValues
, потому что она установленалибо value
, если защита типа прошла успешно (в этот момент value
является AllowedValues
), либо AllowedValues.LOREM_IPSUM
, если защита типа не работает.В любом случае, allowedValue
- это AllowedValues
.
Так что это было бы мое предлагаемое изменение, если вы хотите помочь компилятору понять вещи.Надеюсь, это поможет.Удачи!