2

I have this array:

// I have this as a const since I need it as a type elsewhere
const fruits = ["strawberry", "banana", "orange", "grapefruit"] as const;

Then I try to check if an unknown value (from like a HTTP controller) is present in the array (to prevent lots of x !== y statements), like below:

const input: string = SomeRandomService.getMyString();

if(!fruits.includes(input)) {
  throw new Error("Not present");
}

That results in the following error message on the .includes(input <-- this one):

TS2345: Argument of type 'string' is not assignable to parameter of type '"strawberry" | "banana" | "orange" | "grapefruit"'.

Why does this occur? This seems like valid code to me, because I actually want to do that check to prevent it from not being assignable like TypeScript suggests me to do.

What is the solution to bypass this? (Except doing input as any)

0

2 Answers 2

1

You can cast your fruits to ReadonlyArray<string> which has includes by default but un-modifiable

// I have this as a const since I need it as a type elsewhere
const fruits = ["strawberry", "banana", "orange", "grapefruit"] as const;

const input: string = "testing";

if(!(fruits as ReadonlyArray<string>).includes(input)) {
  throw new Error("Not present");
}

Playground

Sign up to request clarification or add additional context in comments.

Comments

1

There's no easy way to do this, but you can wrap all the messy logic into a type-guarding function:

const fruits = ["strawberry", "banana", "orange", "grapefruit"] as const;

const isFruit = (value: string): value is typeof fruits[number] => {
  return fruits.includes(value as typeof fruits[number])
}

const input: string = "something";

if (!isFruit(input)) {
  throw new Error("Not present");
}
// now input is typed "strawberry"|"banana"|"orange"|"grapefruit"

Playground Link

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.