Given an array of a specific union type, I am trying to determine if a string from a larger set that includes the union type is present in the array during runtime:
const validOptions: ("foo" | "bar")[] = ["foo", "bar"]
type IArrType = typeof validOptions[number]
const key: IArrType | "alien" = "alien" // Could be any random function
const isKeyInArr = validOptions.indexOf(key) > -1 // Error: "alien" cannot be assigned to "foo" or "bar"
// Solution 1:
const isKeyValidCast = validOptions.indexOf(<IArrType>key) > -1
// Solution 2:
const isKeyValidExplicit =
key === "alien" ? false : validOptions.indexOf(key) > -1 // Now works due to type guard
Solution 1 works but lacks elegance. Solution 2 tricks the compiler but may not be the most efficient at runtime. The use of "alien" as a placeholder for any string outside of the union type complicates things.
Is there a way to accomplish this without needing casting or explicit tests? Can the expression be negated to make the type guard work more effectively?
On another note, here is a useful guide on creating a typed tuple from a list of values: Typescript derive union type from tuple/array values