Reputation: 913
I wrote a type for my click handle functions which return a value with the same type of it's parameter, the code is:
type OnClickHandle =<T extends unknown = undefined>(p: T extends infer U ? U : T)=>
T extends infer U ?
U extends number ? number:
U extends string ? string :
U extends undefined ?
void :
void :
void
and then I defined my function like this:
const handleReceive:OnClickHandle = (p:number) => p;
//ERROR:Type '(p: number) => number' is not assignable to type 'OnClickHandle'.
Types of parameters 'p' and 'p' are incompatible.
Type 'T extends infer U ? U : T' is not assignable to type 'number'.
Type 'unknown' is not assignable to type 'number'.
Type 'unknown' is not assignable to type 'number'.ts(2322)
handleReceive(0);
I was frustrated with this message'unknown' is not assignable to type 'number'
,how can I make it works well?
any idea is appreciated !
Upvotes: 6
Views: 25702
Reputation: 1028
type Test<T> = (arg: T) => T;
this is a normal function type, in which the type will be inferred from declaration
you can use it like this
const test:Test<number> = (p:number) => p;
And then there's your way
type Test = <T>(arg: T) => T;
this is a generic function type, in which the type will be inferred from parameters you can use it like this
const test:Test = (p) => p;
test(3) // type is inferred here
so if we are not changing your type declaration, you implementation should look like this
const handleReceive:OnClickHandle = (p) => p; // do not declare type here, it is supposed to be generic
handleReceive(3);
Upvotes: 0
Reputation: 26094
TLDR: I suggest you use the following
type OnClickHandle<T> = (p: T) => T;
const handleReceive: OnClickHandle<number> = (p: number) => p;
Simple and works.
Issues with your code:
You are trying to assign lambda with concrete type to generic function
There are 2 kinds of generics in TS:
You cannot assign a labmda with a concrete type to generic function
type OnClickHandleGenericFunction = <T>(p: T) => T;
const handleReceiveGenFun1: OnClickHandleGenericFunction = (p: number) => p; //ERROR: number not assignable to T
It is highly unlikely that you want write a handler that handles any type f event in the same way, in such case you can assign a generic function to generic function type.
const handleReceiveGenFun: OnClickHandleGenericFunction = <T extends any>(p: T) => p;
Use of unknown
The error you receive says you cannot assign p to unknown. That is not a surprise. See unknown
Convoluted type inferrence
You introduced inferred type U for no reason.
T extends infer U ?
U extends number ? number : void
Could be replaced with
T extends number ? number : void
Upvotes: 4