You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add an overload to Array.prototype.includes and ReadonlyArray.prototype.includes that narrows the type of the searched value when the array is a literal tuple (e.g., declared with as const) containing only primitive literal values such as strings, numbers, booleans, null, or undefined.
This overload enables stricter type checking for includes calls and allows using includes as a type guard only when it is safe and meaningful to do so, avoiding false assumptions when working with general arrays.
interfaceReadonlyArray<T>{includes<U>(s: U,
...args: IsLiteralArray<this>extendstrue
? TextendsU
? [fromIndex?: number]
: never
: never): s is IsLiteralArray<this>extendstrue ? (TextendsU ? T : never) : never;includes<U>(s: U,
...args: TextendsU ? [fromIndex?: number] : never): boolean;}interfaceArray<T>{includes<U>(s: U,
...args: TextendsU ? [fromIndex?: number] : never): TextendsU ? boolean : false;}
Currently, code like the following produces a type error, even though it is semantically correct:
constKEYS=['aaa','bbb','ccc']asconst;functionhandleKey(key: string){if(KEYS.includes(key)){// This should narrow key to 'aaa' | 'bbb' | 'ccc'doSomething(key);}}
To avoid this error, users often resort to unsafe casts or unnecessary widening of the array's type. On the other hand, relaxing the parameter type (e.g., using unknown) can lead to incorrect code such as:
constKEYS=['aaa','bbb','ccc']asconst;functionhandleKey(key: number){if(KEYS.includes(key)){// This is likely a bug, but it won't be caught}}
The proposed overload solves this by enabling proper narrowing only when it is safe (i.e., when the array is a literal tuple of literals), and producing compile-time errors when there is no possible match.
π» Use Cases
What do you want to use this for?
What shortcomings exist with current approaches?
What workarounds are you using in the meantime?
1. What do you want to use this for?
To safely narrow the type of a variable when checking its inclusion in a fixed set of literal values using .includes, especially in configuration validation, value guards, and API parameter checks.
2. What shortcomings exist with current approaches?
includes does not currently act as a type guard even when used with literal tuples.
It requires manual guards or unsafe type assertions.
Overly permissive typing (e.g., accepting unknown) eliminates type safety and allows obvious mistakes.
3. What workarounds are you using in the meantime?
Writing custom type guards (key is 'a' | 'b' | 'c')
Using Set.has() instead of arrays
Using type assertions like as any
Duplicating union types and literal arrays
The text was updated successfully, but these errors were encountered:
The type function is only to determine if it is a literal fixed array, so I did not intend to add that as a utility type, but if it is used in a global type, I would have to add it.
π Search Terms
ReadonlyArray includes type-guard
β Viability Checklist
β Suggestion
Add an overload to
Array.prototype.includes
andReadonlyArray.prototype.includes
that narrows the type of the searched value when the array is a literal tuple (e.g., declared withas const
) containing only primitive literal values such as strings, numbers, booleans,null
, orundefined
.This overload enables stricter type checking for
includes
calls and allows usingincludes
as a type guard only when it is safe and meaningful to do so, avoiding false assumptions when working with general arrays.Supporting Utility Types:
You can try it in the TypeScript Playground here
π Motivating Example
Currently, code like the following produces a type error, even though it is semantically correct:
To avoid this error, users often resort to unsafe casts or unnecessary widening of the array's type. On the other hand, relaxing the parameter type (e.g., using
unknown
) can lead to incorrect code such as:The proposed overload solves this by enabling proper narrowing only when it is safe (i.e., when the array is a literal tuple of literals), and producing compile-time errors when there is no possible match.
π» Use Cases
1. What do you want to use this for?
To safely narrow the type of a variable when checking its inclusion in a fixed set of literal values using
.includes
, especially in configuration validation, value guards, and API parameter checks.2. What shortcomings exist with current approaches?
includes
does not currently act as a type guard even when used with literal tuples.unknown
) eliminates type safety and allows obvious mistakes.3. What workarounds are you using in the meantime?
key is 'a' | 'b' | 'c'
)Set.has()
instead of arraysas any
The text was updated successfully, but these errors were encountered: