Почему этот typescript typeguard не работает

#typescript #typeguards

#typescript #typeguards

Вопрос:

У меня есть следующий код

 const validProtocols = ["https", "http"] as const
type AllProtocols = typeof validProtocols
type Protocol = AllProtocols[number]
function isProtocol(p:unknown): p is Protocol{
  return typeof p === "string" amp;amp; p in validProtocols
}

let parse = (p:string)=>{
  if(isProtocol(p))
    return p
  else
    throw `${p} is not a protocol`
}

console.log(parse("https"))
 

Код компилируется, но последняя строка выдает as isProtocol(p) возвращает false . Что не так?

Код должен использоваться для проверки входных данных вне контроля компилятора, т.Е. Переменных среды.

Ответ №1:

in Оператор проверяет, существует ли свойство для объекта. Например:

 const obj = { prop: 'val' };
const arr = ['val'];

console.log('prop' in obj, 0 in arr); 

Он не проверяет значения, только свойства. Чтобы проверить значения в массиве, используйте .includes (и вам также придется обойти уродливые правила типов .includes , которые делают подобные проверки намного более запутанными, чем можно было бы ожидать):

 function isProtocol(p:unknown): p is Protocol{
  return typeof p === "string" amp;amp; (validProtocols as unknown as Array<string>).includes(p)
}
 

Комментарии:

1. Почему приведение типов? validProtocols — это строковый массив no?

2. Он более специфичен — он напечатан как ["https", "http"] , и, к сожалению, TypeScript не позволяет .includes вызывать элементы, которые могут отсутствовать в массиве. Многие не согласны с дизайнерским решением, поэтому на данный момент для выполнения такой проверки вам понадобится обходной путь, такой как утверждение уродливого типа в ответе.

3. Хорошо, это as const дополнительная информация здесь. blog.logrocket.com / … Спасибо за информацию.