I have a need to make a function return type as conditional type and below is my code
type MyType = "valueA" | "valueB";
type MyTypeOrNull<T> = T extends "valueA" | "valueB" ? MyType : null;
function getValue<T extends string>(value: T) {
if(value === "valueA" || value === "valueB") {
return value as MyTypeOrNull<T>;
}
return null;
}
But it comes with below error
Conversion of type 'T' to type 'MyTypeOrNull<T>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type 'string' is not comparable to type 'MyTypeOrNull<T>'.
question is do I really need to replace
return value as MyTypeOrNull<T>;
to
return value as unknown as MyTypeOrNull<T>;
Your T
claims it extends string
, but MyTypeOrNull
can actually be null
too.
If you replace that with string | null
string | null
instead, it will work fine:
function getValue<T extends (string | null)>(value: T) {
if(value === "valueA" || value === "valueB") {
return value as MyTypeOrNull<T>;
}
return null;
}
In fact, it would work fine - in terms of TS not complaining about it - even if you just casted it without the value check:
function getValue<T extends (string | null)>(value: T) {
return value as MyTypeOrNull<T>;
}
I'm not convinced if that's what you actually intended your value
or the return type to be, but that's what your code is currently saying.
I believe what you actually tried to accomplish is to force TS compiler to determine the type based on the value of the given param. But that is impossible to do - TS works before compilation, and it cannot guess what's the type of the param, if the actual param value will be given in runtime.
I think you'd get closer to your intended solution by looking into the is
keyword, since that's the part of TS that can "pretend" to perform those value checks for you even before runtime, allowing you to get rid of the generally less safe unknown
casting:
type MyType = "valueA" | "valueB";
type MyTypeOrNull = MyType | null;
function isMyTypeOrNull(value: string | null): value is MyTypeOrNull {
return (value === "valueA" || value === "valueB" || value === null);
}
function getValue<T extends string>(value: T): MyTypeOrNull {
if (isMyTypeOrNull(value)){
return value as MyTypeOrNull;
}
return null;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.