Why does this typescript typeguard not work

94 views Asked by At

I have the following code

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" && p in validProtocols
}

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

console.log(parse("https"))

The code compiles but the final line throws as isProtocol(p) is returning false. What is wrong?

The code is to be used for validating input outside the control of the compiler ie: environment variables.

1

There are 1 answers

3
CertainPerformance On BEST ANSWER

The in operator checks whether a property exists on an object. For example:

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

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

It doesn't check values, only properties. To check values in an array, use .includes (and you'll also have to work around the ugly type rules for .includes that make these sorts of checks much messier than one would expect):

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