WEN-JY
WEN-JY

Reputation: 913

typescript Type 'unknown' is not assignable to type 'number'

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

Answers (2)

arslan2012
arslan2012

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

Lesiak
Lesiak

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:

  • 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

Upvotes: 4

Related Questions