(There is no genuine use-case here, so this is my code)
I'm trying to make a function that throws an error if the string is "fish". I was successfully able to do this by using as
, however,
is there any way to avoid using as
for this scenario?
function throwIfFish<S extends string>(string: S): S extends "fish" ? never : S {
if (string === "fish") {
throw new Error("fish");
}
return string as S extends "fish" ? never : S;
// ^ is this unavoidable?
}
CodePudding user response:
The conditional type in question is simple enough, and the result type is "good enough" so that index signature type can work here:
type NeverFish<S extends string> = {
fish: never;
[n: string]: S;
}
function throwIfFish<S extends string>(str: S): NeverFish<S>[S] {
if (str === "fish") {
throw new Error("fish");
} else {
return str;
}
}
let r1 = throwIfFish("f"); // "f"
let r2 = throwIfFish("fish"); // never
CodePudding user response:
Move the signature into another overload:
function throwIfFish<S extends string>(string: S): S extends "fish" ? never : S;
function throwIfFish(string: string) {
if (string === "fish") {
throw new Error("fish");
}
return string;
}
but this means TypeScript will no longer check if the implementation coheres to the overload's signature. Alternatively, you could still use a cast with less repetition:
return string as ReturnType<typeof throwIfFish<S>>;