TypeScript 3.0 error on `unknown` usage

user6440264 picture user6440264 · Jul 29, 2018 · Viewed 13.9k times · Source

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.

Answer

Titian Cernicova-Dragomir picture Titian Cernicova-Dragomir · Jul 29, 2018

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