4 ms·
You could probably do 80% of the inference statically as well. For instance, given something like this: function incrX(obj) { obj.x += 1 } We can infe
by andrewfong 10y ago
You could probably do 80% of the inference statically as well. For instance, given something like this:
function incrX(obj) {
obj.x += 1
}
We can infer incrX expects an object with property x, which is probably an integer. And therefore, a call like `incrX({x: "hello"})` is probably incorrect. In fact, I think this is how type inference in languages like OCaml works.
That said, I do wish statically-typed languages generally had runtime type checking built in. For instance, I can tell Typescript what type of response we're expecting to get from an API call, but that doesn't mean the compiled Typescript will warn me if the API call ends up with a different type.
- masklinn 10y ago> We can infer incrX expects an object with property x, which is probably an integer. And therefore, a call like `incrX({x: "hello"})` is probably incorrect. In fact, I think this is how type inference in languages like OCaml works. Except OCaml's typing is much stricter than JS's, in JS `obj.x += 1` is perfectly valid if `x` is a string. In fact due to all the runtime type conversion protocols you can have pretty much anything as `x` and have `obj.x += 1` succeed. So that requires a strict break and separation with JS semantics and treating JS (or whatever) as an implementation detail and "assembly", which is the opposite of Typescript's purpose (it's more of an Elm or Purescript or ocaml_in_js thing) > That said, I do wish statically-typed languages generally had runtime type checking built in. Statically typed languages with lots of holes (at the type-system level) like Java or C# do have runtime checks. Those with less holes like OCaml or Haskell don't as the only way to get the "wrong" types at runtime is to have wilfully undermined the type system in which case the developer is on the hook for making sure they do that correctly. > For instance, I can tell Typescript what type of response we're expecting to get from an API call, but that doesn't mean the compiled Typescript will warn me if the API call ends up with a different type. That would require TypeScript having its own runtime rather than compiling to regular Javascript, or it would require that TypeScript inject a fuckton of type checks which would make the output orders of magnitude slower (both from the overhead of javascript-level type-checking and from the increase in code size and decrease in JIT optimisation opportunities).
- dllthomas 10y agoTo expand, with regard to (GHC) Haskell: you can perform run-time type checks with the Typeable typeclass, and you can forgo compile-time checks in favor of runtime checks with Data.Dynamic. You can also replace compile-time detected type errors with "if this is executed, explode", with the -fdefer-type-errors flag. And of course, in any typed language you can apply sufficiently general types that you need to perform manual checks for safety.
- jdmichal 10y agoTypescript couldn't actually do this for interfaces. Typescript interfaces don't exist post-compilation, and the only way to check for them would be to ensure that every expected property exists on the incoming object. This has a very annoying side effect of never being able to exclude interfaces from a union type: function doStuff(thing : string | SomeInterface) : void { if (typeof(thing) === "string") { // thing is still typed as string | SomeInterface, // because there's no guarantee that the // string object doesn't implement the interface. // If SomeInterface was a class instead of an interface, // then thing would only have the string type here. } } Also, this is ignoring the fact that you would also need to check the parameter types on an incoming function, which AFAIK isn't possible at all.
- evmar 10y agoI work with TypeScript fairly closely and was surprised at your example, because I was sure that this already works. It turns out the type narrowing is actually special-cased on only some particular AST. You can see it working here, where "charAt" would not be allowed if it was still |SomeInterface: http://www.typescriptlang.org/play/#src=interface%20SomeInterface%20%7Bx%3A%20number%7D%0Afunction%20doStuff(thing%20%3A%20string%20%7C%20SomeInterface)%20%3A%20void%20%7B%0A%20%20%20%20%20%20%20%20if%20(typeof%20thing%20%3D%3D%3D%20%22string%22)%20%7B%0A%09%09%09thing.charAt(0)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D http://www.typescriptlang.org/play/#src=interface%20SomeInte...
- jdmichal 10y agoSo I started exploring this again today, and it ends up that what you had works, but if I parens on the typeof check, it no longer works: if (typeof(x) === "string") I opened an issue: https://github.com/Microsoft/TypeScript/issues/9391 https://github.com/Microsoft/TypeScript/issues/9391 Thanks for the help!