bradgonesurfing
bradgonesurfing

Reputation: 32162

Why does this typescript typeguard not work

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.

Upvotes: 1

Views: 93

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370679

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)
}

Upvotes: 1

Related Questions