1

Here, I test TypeScript3.0 unkown type.

https://blogs.msdn.microsoft.com/typescript/2018/07/12/announcing-typescript-3-0-rc/#the-unknown-type

TypeScript 3.0 introduces a new type called unknown that does exactly that. Much like any, any value is assignable to unknown; however, unlike any, you cannot access any properties on values with the type unknown, nor can you call/construct them. Furthermore, values of type unknown can only be assigned to unknown or any.

I play with some Church eoncoding stuff, and testing unknown type to every argument of functions, I have an error as below:

const log = (m: unknown) => {
    console.log(m); //IO
    return m;
};

const I = (x:unknown) => x;
const L = (x:unknown) => (y:unknown) => x;
const P = (x:unknown) => (y:unknown) => (z:Function) => z(x)(y);
//z is a binary operator Function!

const Left = L;
const Right = L(I);

log("Left Right test---------");
log(
    Left("boy")("girl")  // boy
);
log(
    Right("boy")("girl")  //TypeScript Type Error here
);

Error:

church.ts:20:9 - error TS2571: Object is of type 'unknown'.

20         Right("boy")("girl")
           ~~~~~~~~~~~~

Just in case, this is well-tested in vanilla JS, but I simply want to know how to resolve this error without using any type.

Thanks.

  • Did you expect something different? The result of `L(I)("boy")` is typed `unknown`, and the quote you include explicitly states of such types *"nor can you call/construct them"*. – jonrsharpe Jul 29 '18 at 12:47
  • Can you clarify which quote states such types "nor can you call/construct them". –  Jul 29 '18 at 12:50
  • ...literally that one in the yellow box that you posted in your question. – jonrsharpe Jul 29 '18 at 12:51
  • @jonrsharpe , thanks, and the issue is not what I expected, but I simply want to know how to resolve this error without using any type. –  Jul 29 '18 at 12:53

1 Answers1

2

Quite simply here I don't think you should use unknown but rather a generic function as there are obvious relations between the argument to L and the final return type:

const I = (x:unknown) => x;
const L = <T>(x:T) => (y:unknown) => x;

const Left = L;
const Right = L(I); 

log("Left Right test---------");
log(
  Left("boy")("girl")  // boy
);
log(
  Right("boy")("girl")  //all ok 
);

I would use unknown much like any as a last resort type when the type is not only unknown when writing the function (where we can use regular types) but also unknowable when calling the function (this is when I would generic type parameters).

If for some reason generics are not feasible the only way to get around this is with a type assertion, as you have information the type system lost in this case:

(Right("boy") as ((x:unknown)=> unknown))("girl")  //all ok 
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • Thanks again! In fact, as I mentioned in the previous post, I am sort of seeking a possibility to avoid Generics as much as possible, and wonder how `unknown` behaves in this typing world :) In fact, I sort of succeeded so, and please review my own answer https://stackoverflow.com/a/51581887/6440264 and I'm grateful to hear your thought. –  Jul 29 '18 at 15:40
  • @bayesian-study Don't avoid generics, embrace them! :) They are indispensable in the typescript type system. `unknown` may offer similar results in some specific scenarios but for sure not all. – Titian Cernicova-Dragomir Jul 29 '18 at 16:23