Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Ask HN: TypeScript experts, is this a type checking issue?
5 points by chupa-chups on Sept 1, 2019 | hide | past | favorite | 8 comments
The following ts code both compiles (with all checks active) and passes tslint without complaints:

  type sig = (p: number) => string;
  const x = (p: any) => p + 1;
  const y: sig = x;
  alert(typeof y(5));
Obviously the alert message will (and does) display 'number'.

IntelliJ spots the problem though ('x' should probably not be assigned to 'y').

(Apologies if this is too stackoverflow-y, but I don't expect a "solution", I'm just interested in opinions)



any is assignable to anything so what you’re seeing here is the expected behavior.

What I’d recommend is not to use any (and enable the linter rules to disable it) and rather use unknown (which is assignable to nothing) or generics.

On a more general note, typescript is not sound (though it works well in practice) and you’ll always be able to find incorrect code that typechecks, even without using any.


Thanks for the reply. I'm writing a ts parser and stumbled over this.

The reason I find it strange is that in this case it appears detectable that the return type will not match (independent of the any type in the parameter).

Is there a reason not to check this I'm not seeing?

By the way, I am quite amazed at the quality (and depth) of the typescript type inference & check model (despite it being "not sound" to quote you).


The reason is that any is an escape mechanism. Typescript will never complain about anything when dealing with this type. Its use case is to perform a step by step migrations from js or to deal with rare corner cases when you can prove yourself that the code is correct.


The type of x is (p: any) => any. It will be assignable to sig.


I don't know TS, but instead of alert(typeof y(5)) why not try alert(typeof y('a')) I would hope you get a compile error. Looking at the code, I would guess that the "any" means that it's essentially a parameterised type. In my ideal world, it wouldn't mean that you can put literally any type in there at any time -- just that you can put any type that will satisfy the type checker. Because you are using it p as a number, it satisfies the type checker.

Another thing you can try is to pass x in as a parameter to a function. I would expect that this would not compile -- because the compiler can't guarantee (without jumping through incredible hoops) that x is always going to use p as a number. If it does compile, try to pass 2 functions: one numerical and one that uses chars. If that compiles, then I think you have a legitimate error in the type checker. Otherwise I think it's just fine.


Sadly (but understandably) typeof is a runtime expression.


What would the problem be? If you use `any`, any code that touches that value can no longer be properly type checked. The type of x is `(p: any) => any` (if p is a string, p + 1 will return a string as well), so it can be assigned to y just fine - at least as far as the type annotations are concerned.


I think your original hunch is correct. This is a little too stackoverflow-y.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: