I am getting this error, Where as U is number and returning the number too.
Type 'number' is not assignable to type 'U'.
function foo<T extends string, U extends number>(a: T): U {
return a; // error in this line
}
foo<string, number>('12')
CodePudding user response:
I believe it worth using overloading here:
type UnsafeNumber = number & { tag?: 'UnsafeNumber' }
type ParseInt<Str extends string> =
Str extends `${infer Digit extends number}`
? Digit
: UnsafeNumber
function foo<T extends string>(a: T): ParseInt<T>
function foo<T extends string>(a: T) {
return a;
}
type Result = ParseInt<'.2'>
const _ = foo('42') // 42
const __ = foo('4.2') // 4.2
const ___ = foo('s03') // UnsafeNumber
Since TS does not distinguish number
and NaN
I have provided UnsafeNumber
which corresponds to NaN
. However, it is still not safe and I would recommend you to use parseItn
function
ParseInt utility type
Since TS 4.8, TS is able to infer literal number from stringified number. See docs. It means that TS is able to infer 100
from "100"
. It means that when you provide "42"
as an argument, TS will be able to infer it as a digit 100
. If you will provide just a regular string, TS will not be able to do it and false
branch in conditional type will be evaluated, or in other words UnsafeType
will be returned.
UnsafeType
is just a regular number
with using of branded type
pattern. So TS will be able to distinguish regular number
and UnsafeNumber
. UnsafeNumber
means that TS is not able to infer digit number from string and it might be NaN
If you are interested and type inference and validation you can check my this article about number inference and inference on function arguments in general or this answer
CodePudding user response:
you need to use as
keyword to cast the return value type
function foo<T extends string, U extends number>(a: T): U {
return a as U;
}
foo<string, number>('12')