Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: Unexpected unknown

Tags:

typescript

I've been working with TypeScript quite a bit lately and stumbled across a problem that is confusing to me. I've put the problem into an example which looks like the following:

type Options<T> = {
  props: T;
  g: (x: T) => void;
};

function f<T>(options: Options<T>) {
  console.log(options);
}

// Example 1 (x and props expected type)
f({
  props: {
    foo: {
      a: 200,
      bar: () => {}
    }
  },
  g(x) {
    // x is the expected type
    console.log(x)
  }
});

// Example 2 (x and props unknown)
f({
  props: {
    foo: {
      a: 100,
      bar: function() {}
    }
  },
  g(x) {
    // x is unknown
    console.log(x)
  }
});

When hovering over props in the first example, you will see that it has the expected type. And although barely anything changed in the second example props is of type unknown. Why is that? Here is the example above in TS Playground.

like image 723
Jens Avatar asked Oct 17 '20 13:10

Jens


People also ask

How do you handle unknown in typescript?

Anything is assignable to unknown , but unknown is not assignable to anything but itself. So we can do const foo: unknown = 'foo' , but we cannot do, out of the box, const bar: string = foo if foo is unknown .

How do you change the unknown type in typescript?

Typescript doesn't allow you to use an unknown type before casting it. You would need to cast it, in order to typescript to allow you to use it. As you can see from the above examples, the unknown type forces you to determine what a variable typed as unknown is, either through type casting or type narrowing.

How do I fix unknown type?

The "Object is of type unknown" error occurs when we try to access a property on a value that has a type of unknown . To solve the error, use a type guard to narrow down the type of the object before accessing a property, e.g. if (err instanceof Error) {} . Copied!

When should you use the unknown keyword?

unknown and any are 2 special types that can hold any value. unknown is recommended over any because it provides safer typing — you have to use type assertion or narrow to a specific type if you want to perform operations on unknown .

What is the unknown type in typescript?

TypeScript provides a variety of type definitions. Some of them are common such as strings, numbers, arrays, booleans to more custom interfaces and classes. New types came with the release of TypeScript 3.0. One of them is the unknown type which we will cover in this article. What is the Unknown Type? Anything is assignable to unknown.

Why does typescript not allow string types?

Typescript is just a type system: all those types just get thrown away when it compiles, it won’t change your code for you. You’re also declaring an undefined variable ( let str; ), and the type of that is unknown. You then assign a string to it. This isn’t an issue, TS will allow this.

How to fix type 'unknown' is not assignable to type error?

The "Type 'unknown' is not assignable to type" error occurs when we try to assign a value with a type of `unknown` to a value of a different type. To solve the error, use a type assertion or a type guard to verify that the two values have compatible types before the assignment. HomeAboutContacts HomeAboutContacts GitHubLinkedinTwitter

How to solve the uncaught SyntaxError “unexpected token import” in typescript?

To solve the "Uncaught SyntaxError: Unexpected token import" in TypeScript, set the module option to commonjs in your tsconfig.json file and make sure to compile your TypeScript files (e.g. with ts-node), and not to run them directly with node. Open your tsconfig.json file and make sure the module option is set to commonjs.


1 Answers

This is a design limitation in TypeScript; see microsoft/TypeScript#38845. Apparently (from this comment):

An arrow function with no parameters is not context sensitive, but a function expression with no parameters is context sensitive because of the implicit this parameter. Anything that is context sensitive is excluded from the first phase of type inference, which is the phase that determines the types we'll use for contextually typed parameters.

It looks like inference for T succeeds when the foo.bar property is an arrow function because there's no contextual this to worry about. And so a contextual type is successfully assigned to the x parameter of g, and everything proceeds as you want. But when the value of foo.bar is a function expression, the compiler needs context to figure out what this is, and T cannot be inferred in time to figure out a contextual type for g's parameter and it ends up becoming unknown.

like image 188
jcalz Avatar answered Sep 20 '22 05:09

jcalz