6

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 !

1
  • my typescript version :3.7.2 Commented Aug 19, 2020 at 7:42

2 Answers 2

4

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:

  • Generic Types
  • Generic functions

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
Sign up to request clarification or add additional context in comments.

1 Comment

thx a lot, are there more articles about Generic Types and Generic functions?newer to ts
0
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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.