I have 2 sets of keys: KEY_SET_1 and KEY_SET_2. KEY_SET_1 has keys A to D while KEY_SET_2 has keys E to H. I have a function that needs to handle key in both key sets differently. However, I run into an error that says
Argument of type ‘AllKeySetType’ is not assignable to parameter of type ‘"A" | "B" | "C" | "D"’. Type ‘"E"’ is not assignable to type ‘"A" | "B" | "C" | "D"’.".
I wonder what is the best way to go about it in TypeScript in this case? Thanks.
const KEY_SET_1 = ['A', 'B', 'C', 'D'] as const;
const KEY_SET_2 = ['E', 'F', 'G', 'H'] as const;
type KeySet1Type = (typeof KEY_SET_1)[number];
type KeySet2Type = (typeof KEY_SET_2)[number];
type AllKeySetType = KeySet1Type | KeySet2Type;
const handleKey = (key: AllKeySetType) => {
if (KEY_SET_1.includes(key)){ // <- Error here
// Handle key set 1
}else{
// Handle key set 2
}
}
I can make the error disappears by casting key as KeySet1Type but I am not sure if this is the best way to go about it.
>Solution :
I can make the error disappears by casting key as KeySet1Type
but I am not sure if this is the best way to go about it.
Indeed, it’s rather the type of KEY_SET_1 that is the problem there and should be cast to readonly string[]. But I suppose you’d want an actual type guard there, so that the type of key is strictly known to the compiler after the test, so here is how I’d rewrite it:
const KEY_SET_1 = ['A', 'B', 'C', 'D'] as const;
const KEY_SET_2 = ['E', 'F', 'G', 'H'] as const;
type KeySet1Type = (typeof KEY_SET_1)[number];
type KeySet2Type = (typeof KEY_SET_2)[number];
type AllKeySetType = KeySet1Type | KeySet2Type;
function isOfKeySet<KS extends AllKeySetType>(ks: readonly KS[], key: string): key is KS {
return (ks as readonly string[]).includes(key);
}
const handleKey = (key: AllKeySetType) => {
if (isOfKeySet(KEY_SET_1, key)) {
key; // (parameter) key: "A" | "B" | "C" | "D"
} else {
key; // (parameter) key: "E" | "F" | "G" | "H"
}
}