Created
December 7, 2016 02:12
-
-
Save nafg/b58b1673886f684e3c89fdd44d5acf10 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Naftoli Gugenheim 🎻 [4:58 PM] | |
Ok where to begin... how about the title | |
[4:58] | |
> You Might Not Need TypeScript (or Static Types) | |
[4:59] | |
Who is he addressing? Has anyone argued that you "need" them? | |
Binyomin Greenes [4:59 PM] | |
:insert popcorn gif here: | |
Naftoli Gugenheim 🎻 [5:01 PM] | |
> Before you do, please read “The Shocking Secret of Static Types”. | |
[5:02] | |
Won't go into that, but the studies are not comparable | |
[5:02] | |
> Type annotations obviously create more syntax noise, and that syntax makes code harder to read, and harder to maintain | |
[5:03] | |
That's a statement about specific languages, not about static types. There are many languages where the types create almost no syntactic noise. | |
[5:03] | |
Besides, I could argue "descriptive variable names create more noise, and that noise makes code harder to read and harder to maintain." | |
[5:04] | |
The problem with that argument of course is that it's not _noise_ it's _signal_, and signal that's very conducive to maintenance | |
[5:04] | |
The same is true of types, _only much more_ | |
[5:05] | |
_Types tell you more about what a function does than its name and its argument names -- *if you use them right*_ (edited) | |
[5:06] | |
The difference is that names can be wrong (copy-paste error, forgot to update after refactor, etc.) while types can't be | |
[5:07] | |
>>>But the drawbacks go a little deeper. Specifically, static types can make all of these things harder (not impossible, just more complicated than they need to be): | |
* Generic functions & polymorphism | |
* Higher order functions | |
* Object composition | |
Shaya Goldberg [5:08 PM] | |
@naftoligug I think we need a full blogpost from you... Slack wont do this justice | |
Naftoli Gugenheim 🎻 [5:08 PM] | |
hehe | |
[5:08] | |
Ok so first of all, _yes types give you more work to do_ | |
[5:09] | |
The question of course is whether it's worth it | |
[5:09] | |
In some languages that work may not be more writing | |
[5:10] | |
But almost by definition, it requires more _thinking_ (edited) | |
[5:10] | |
So they definitely give you more work to do | |
[5:10] | |
The question is, what does that work accomplish? | |
Binyomin Greenes [5:12 PM] | |
>>>Ok so first of all, _yes types give you more work to do_ | |
arguable... | |
(edited) | |
Naftoli Gugenheim 🎻 [5:12 PM] | |
One answer is, it formalizes the contract of your code in a way that can be reasoned about predictably (edited) | |
[5:14] | |
https://frumdevs.slack.com/archives/javascript/p1481062202000209 | |
Naftoli Gugenheim 🎻 | |
But almost by definition, it requires more _thinking_ | |
Posted in #javascriptToday at 5:10 PM | |
[5:14] | |
Some languages force you to do that thinking up front (which IMO is a good thing) | |
[5:15] | |
Others (namely structural-type-inferring languages) may not make you do the thinking up front, (edited) | |
[5:15] | |
but they still formalize the contracts in a way that can be reasoned about and enforced | |
Gavriel Harbater [5:16 PM] | |
>Ok so first of all, _yes types give you more work to do_ | |
(edited) | |
[5:16] | |
I disagree. Measure once and cut twice or measure twice and cut once | |
Naftoli Gugenheim 🎻 [5:16 PM] | |
Exactly! | |
[5:16] | |
The key is that the allure of untyped languages is an illusion! You always end up having to worry about types. | |
[5:17] | |
The question is whether there is going to be a type system to help you do so | |
[5:17] | |
That comes up later in the article, but let's go in order (edited) | |
[5:18] | |
> A generic function is a function that can operate on parameters of more than one type. For example, a function that calculates sums might work for numbers, but could also work with objects which supply a .valueOf() method that returns a number (note, in JS, numbers have a .valueOf() method, which makes it possible to treat both types using identical internal logic). | |
[5:21] | |
One word: parametricity | |
[5:21] | |
Here's one article on the subject (warning: author is a bit extremist) -- http://blog.tmorris.net/posts/identifier-names/index.html | |
[5:23] | |
Moreover this paragraph is really using circular reasoning. _Assuming duck typing_, "having .valueOf()" is a type | |
Mordy Tikotzky 👤 [5:23 PM] | |
yeah dont get that | |
[5:23] | |
this works in TS | |
[5:24] | |
```function takesValueOf(param: { valueOf: () => number }) { | |
return param.valueOf(); | |
} | |
const x = takesValueOf(10); | |
const y = takesValueOf({ valueOf() { return 10 } });``` | |
Naftoli Gugenheim 🎻 [5:25 PM] | |
My point is, there are better type systems than duck typing, so saying untyped JS can do generics is disingenuous (edited) | |
[5:26] | |
Again, is this about TS or about static typing in general? Those are very different subjects | |
Mordy Tikotzky 👤 [5:27 PM] | |
I dont think we’re arguing | |
Naftoli Gugenheim 🎻 [5:27 PM] | |
(as in most cases of a specific instance vs. general principle) | |
Mordy Tikotzky 👤 [5:27 PM] | |
Im agreeing that the complaint about generic functions is a non issue | |
Naftoli Gugenheim 🎻 [5:27 PM] | |
Right but I think for a different reason? | |
[5:28] | |
> For example, with JavaScript + React, we can use React’s PropTypes for automated dynamic type checks in development mode | |
[5:28] | |
Ummm... I thought specifying types was too verbose? I guess he likes that syntax better? | |
[5:28] | |
> and even compile the type checks away for production deployment, since they’re no longer needed once you’ve verified that the correct types are being passed. | |
[5:29] | |
Nonono!!!! | |
[5:29] | |
Have you _proved_ that incorrect types are _never_ passed? | |
[5:29] | |
Of course not. Only static analysis can do that. React prop types cannot. | |
[5:30] | |
Of course for a sufficiently simple program it might be safe to assume... | |
[5:30] | |
or it might not | |
[5:30] | |
> In other words, the application doesn’t need to take a performance hit to benefit from runtime type checking. | |
[5:30] | |
Mmm. You mean runtime type checks have a downside so just delete them in prod? | |
[5:32] | |
> Here’s a stripped-down example of how you might enhance runtime type checking in JavaScript: | |
[5:32] | |
Ok from here it just makes zero sense. He just invented a mechanism for runtime-enforced type annotations | |
[5:32] | |
So, the worst of both worlds: verbose and slow | |
[5:33] | |
> If you’re thinking this sounds like a lot of trouble compared to static types, consider that runtime type checking complexity is usually hidden inside a framework or library. The creator of the app above only needs to worry about the createEmployee() function and its required property. In other words, it can be less work than writing the equivalent static type annotations. | |
[5:33] | |
Can anyone explain this to me? How is this at all less work than the equivalent statically typed program? | |
[5:33] | |
> Type errors are not the only source of bugs, | |
(edited) | |
[5:34] | |
Duh. That isn't the point. _Almost any bug can be prevented with sufficiently strong types._ | |
[5:35] | |
Types are not there to prevent type errors, they're there to lift logic errors into the realm of static analysis | |
[5:35] | |
> and throwing an exception is not the worst thing that can happen in response to a bug. | |
[5:36] | |
If your two choices are (1) don't compile and (2) crash and burn in production, yeah I think I'd go with #1 just about every time | |
[5:36] | |
And the times that I don't, I can just not use such strong types | |
[5:37] | |
> Hopefully you’ve taken my advice on using TDD. Static types are great at catching type errors, but have little effect on over-all bug density, TDD can reduce production bug density by 40% — 80%. | |
[5:37] | |
Ok here's something to think about: _Types *are* TDD_ | |
[5:38] | |
Types are "tests" that are _proven_ statically | |
[5:39] | |
Almost no test "proves" anything completely, because it cannot test every single possible input. Even property tests can only generate a finite number of random scenarios. | |
[5:40] | |
OTOH types are a proof. If a function is String => Int, (in the absence of subverting the type system and non-termination) it is _impossible_ for it to process a non-String or produce a non-Int | |
[5:41] | |
(by subverting the type system I mean things like casting, and by non-termination I mean things like throwing exceptions, infinite loops, and null) | |
[5:42] | |
> Add runtime type checks to the mix, and you’ve got a 3-layered line of defense against shipping bugs. | |
[5:42] | |
Again, are you pro types or not? How are runtime type checks better than static ones? They're strictly worse | |
[5:43] | |
>>>Duck typing is beneficial because at design time, you don’t have any way to know all of the future requirements of the program. What if in the future you need a rubber duck drone which can still fly and quack like a regular duck? | |
With nominal static types, you’ll need to change the type signature of every function that uses ducks everywhere in your program — a process that is not easily aided by automated refactoring tools because the functions that need changing don’t yet know that rubber duck drones exist. | |
With duck types and certain structural type systems, you don’t need to change signatures to accommodate rubber duck drones. | |
[5:44] | |
This is a separate discussion: ad-hoc polymorphism | |
[5:44] | |
This is not a flaw of static types in general, it's a flaw of certain type systems like Java, C#, etc. | |
[5:44] | |
One of the best solutions is type classes... but again that's a separate discussion | |
[5:45] | |
Also he seems to associate structural types with dynamic types, which is wrong (see Elm, Go, etc.) | |
Naftoli Gugenheim 🎻 [5:58 PM] | |
There's a lot more silliness | |
[5:58] | |
>>>One great thing about TypeScript is that when the inference capabilities inevitably get a signature wrong (which frequently happens when a function wraps another function), TypeScript allows you to manually assign an interface to something so that correct type hints get displayed in your editor. | |
I wish there was an optional way to do that built into JavaScript. | |
[5:59] | |
Hmm, optional static types? But they would have to be built into JS? What's wrong with using another langauge? | |
[6:00] | |
> Any dev tool that can grok a dependency tree and has type inference and data flow analysis can do most of the same automated refactors you’ve come to expect from static type tools. e.g., Tern.js. | |
[6:01] | |
Umm no. _It is mathematically impossible_ to do reliable static analysis in a dynamic language | |
[6:03] | |
This is why it is _impossible_ to compile dynamic languages with incompatibe type systems to JS without a big performance hit: http://www.lihaoyi.com/post/FromfirstprinciplesWhyIbetonScalajs.html#static-optimizability (edited) | |
[6:04] | |
> In multiple decades of software development, I can count on one hand the number of times I’ve spent more than a few minutes manually refactoring something in a way that can be substantially assisted by static types. | |
[6:04] | |
As opposed to automatically refactoring via tooling? Then I won't argue | |
[6:05] | |
But seriously, name one refactoring that isn't substantially assisted by static types? | |
[6:06] | |
I get the impression that people used to dynamic languages have a much more limited idea of what you can do with refactoring | |
[6:06] | |
> Every decent editor has good autocomplete plugins available. | |
[6:06] | |
Yeah, and what about the many cases where due to lack of static types the available autocomplete _is not reliably determinable_? (edited) | |
[6:07] | |
> What About Identifier Name Typos? | |
ditto |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment