> Porting to a typed language helped prevent type errors in a typeless language. Who woulda thunk?
You say this sarcastically, but every JS-related thread on HN turns into a flamewar between type lovers and haters.
The type haters make exactly the argument you're mocking: that typeless languages do not result in more type errors. Their reasoning is along the lines of, "I don't need a type system because I'm a professional and don't make mistakes."
That sounds laughable or like an exaggeration, but it's a surprisingly common line of thinking. The buggiest code I ever worked on was a PHP code base written by someone who had been coding for 20 years and had a Master's in CS. Before I inherited the code, he told me, "I code in the terminal. I don't need IDE features because I don't really make mistakes in PHP anymore."
That of course is not the argument at all. The argument is that the cost of working with static types exceeds the benefits. Finding type errors is obviously a benefit, while not finding them (or finding them only at runtime) is a cost. The question is what other costs and benefits there are, and how to compare them. Nobody agrees on that, nor ever will.
This argument will never be resolved because it's dominated by psychological factors. Once you've adapted to environment A, A's costs (e.g. hoops the compiler makes you jump through / time spent tracking down type errors) become habitual and you don't notice them anymore. Meanwhile the costs of unfamiliar environment B are extremely highlighted in your attention. Similarly, if you like and identify with A, its benefits will be top-of-mind for you, while if you don't like B (and nobody likes B), you'll discount its benefits.
It gets worse. Sometimes benefits are costs until you make it through a learning curve. An example is parentheses in Lisp. They stick out like a sore thumb until one day they don't. Later you realize that they were a liberating force all along, and you now have anti-gravity powers you never dreamt of. (<-- This is an example of how people talk when they are adapted to an environment whose costs they no longer count and whose benefits are top-of-mind for them.) We can't even agree on what the costs and benefits are, let alone how to measure them.
It's no wonder that people feel so strongly about this dispute. When you don't count the costs of your preferred environment, and only count the benefits, it gets obvious pretty quickly that other people are idiots. For some reason the idiots feel the opposite and perversely insist on it.
It gets worse. Imagine that you're a decent, fairminded sort and so, magnanimously as is your wont, you decide to give the idiots a fair shake—you know, just to verify that you're being fair and whatnot. You fire up whatever it is (Clojure? OCaml? needless to say, you make a charitable choice) and start programming for a while. What happens? All the costs of unfamiliarity hit you in the face. Not one of the benefits that has lived at the top of your mind for years is anywhere to be seen. This thing doesn't even catch trivial type errors at compile time! / I can't even execute this bit of code in a REPL! This is a painful experience. It can even be an enraging one, for example if you are forced for some extraneous reason to work on a system you didn't create using tools you don't like. Most people who go through that experience once have their views solidified for life. Meanwhile someone else had the opposite experience.
Given how passionately people feel about this and the certainty in forum threads about it, it's curious (or maybe to be expected) that the question of published evidence comes up so rarely. HN user luu did the definitive survey on this: https://danluu.com/empirical-pl/. The short version is that such studies as there are don't address the core question and/or find insignificant effects and/or their designs tip obviously to one side or the other (and I do mean obviously, like comparing Peter Norvig's code to that of random undergrads).
Bias dominates every other factor, put together, times at least 10. As long as that's true, we can't say anything rational without genuinely accounting for bias. Do we actually know how to do that? The studies don't seem able to. These debates certainly don't, nor do they try. Maybe the interesting phenomenon here is actually the bias itself. Maybe it's not that we like an environment because we're more productive in it, but that we're more productive because we like it. Maybe we should get better at liking things.
The debate about this tends to remain stuck at a low level because once you've been around the block enough times you realize that it hurts to bang your head against a wall so you stop. Thus the vocal population undergoes a perpetual exodus of the experienced, but makes up for it with a fresh supply of enthusiasts, reminding one of the adage, "I arrive at the office late, but make up for it by leaving early."
Great comment. I am part of the minority that is dreading being forced to use Typescript some day, at least until they come up with a solution to annotate partial function application and the like.
TS solves problems I don’t have, and promotes a style I don’t want. I don’t want thousands of global symbols in hundreds of files in my project. At least TS has the decency to infer types in some cases, or at least put the type clutter after an identifier instead of before it, but it’s usually only superfluous clutter to me personally.
I realize that many people like TS. I just hope they understand why some of us are less enthusiastic.
I think you mean currying, right? It's been supported at close to the same level as Haskell for 3+ years[1].
> TS solves problems I don’t have
To me, it solves: 1) devs getting lazy on a team, 2) catching my mistakes before runtime, 3) correctly using library APIs, and 4) refactoring.
All of these might be low-value to you, though. I think #4 is the biggest time-saver because it enables automated refactoring (through the IDE) that isn't possible with plain JS.
> I don’t want thousands of global symbols in hundreds of files in my project.
I'm curious what you mean by this. Are you saying that TypeScript creates global symbols that weren't there before?
You can configure TypeScript so that it doesn't have any symbols from outside your project at all. For example, you can set it to import the types found in Node or on the web, or you can just skip them.
Yes, implicit currying where supplying the final arg actually calls the underlying function is one kind of partial function application. Ramda is one thing I use.
I also use an in-house library to explicitly apply arguments to return a a new function, which allows you to produce 0 arity or variadic functions.
I’m glad somebody has a work around for using Ramda in TS, but it looks every bit as “fun” as generics in Java, which I think have wasted more of my time than they have ever saved.
It is essentially correct that the discussion on typing occurs at the least nuanced level of discourse. I've been at fault doing this myself. The distinction between different sorts of type systems and the relative conservation of the different analyses required to produce well typed programs is rarely brought up. I have a general saying that you shouldn't listen to people unless they can explain a point of view in terms of its tradeoffs. Very few real problems have absolutist solutions. I'm currently working my way through Types and Programming Languages and hope to one day present a more technical and thought out explanations of the tradeoffs present amongst untyped and the various levels of typed systems.
Like you, I think the truth is between the extremes. My original post was just pointing out that the extreme of type-hate is not uncommon here. The opposite appears to be true as well.
I'm not sure I do think the truth is between the extremes, but if I came across that way I did a good enough job of it for the purposes of writing that comment!
It's not really helpful to use a label like "type-haters" or "type-hate". I mean, it's helpful in the sense that it shows how tribalistic the arguments are (just replace "$X-haters" with enough Xs and you'll get the idea). But other ways of talking are more helpful.
On a related note: don't you think it's interesting how personal it feels? To some extent that's because the people who don't care that much select themselves out of the conversation to begin with. But I think it's fascinating even after pricing that in.
> It's not really helpful to use a label like "type-haters" or "type-hate"
> don't you think it's interesting how personal it feels?
I take your point and will avoid it in the future. I used it precisely because, as you say, people are very emotional about it and take it personally. I meant to imply that these were not necessarily good-faith arguers having a rational discussion, but rather participants in a flamewar. This general thread seems to be a mix of both reason and flame.
As for why it's personal, I don't know exactly and do find it interesting. Part of it is likely that people have invested a lot of time into one stack or another, and that becomes an emotional issue. If I spent 10 years becoming a PHP expert, I'll be more upset if someone says PHP is garbage. It suggests my skills or prospects are poor.
After that, I think people are saying things like, "People who use TypeScript are stupid/lazy/etc.", or "People who don't use TypeScript are stupid/ignorant/etc.". Then the emotion may come from the conflict itself, not from the actual position someone is holding.
Now I'm sure that many feel like that, but I don't think it's the majority, but I also don't know.
Here are some more arguments against types (don't necessarily agree with all of them myself, but for reference in the future when you want to write from the perspective of someone who feels more productive without types):
- There are other, more flexible ways to solve the same problems you solve with typing, the clojure.spec way is one of them
- You lose flexibility when suddenly everything is locked to each other by name. Even if Account and Person both has a first and last name fields, you can't use both of them if the function is expecting a Account and only use the first and last name. Then you need to add an interface, name it something, then make Account and Person be based on that. Now the function is locked to the interface, and so on
- Type checking is a very basic form of testing that doesn't solve the most common, annoying and hard-to-track down bugs, logic bugs.
- Metaprogramming becomes harder. Not impossible, just harder.
- Types (at least in TypeScript and other languages I've been using in the past) disappear in runtime, so you can't really use them. It's just a tool for you to tell the compiler what something is so it can say "no, you did wrong here"
Now I'm neither a type lover nor hater. I just want to use the right solution for the right problem, sometimes, that's making a program that will take longer time to write but specification is set in stone and requirements won't change, so types will help you a lot. Other times, it's in a very dynamic and experimental environment where you have to be able to apply changes as quickly as possible and minor errors don't matter as much, as long as you can move forward fast and test theories. Then you can go back and refactor things.
> You lose flexibility when suddenly everything is locked to each other by name.
This is only true of nominally typed languages (such as... most typed languages). TypeScript is a notable exception: values just have to have the same property names and types and they'll fit. The language's philosophy is basically to describe the way people write JS rather than prescribe how people should write it, so idiomatic JS is usually easy to express in TypeScript.
There are some caveats to the structural type system in TypeScript. The most glaring of which is multiple versions of the same typings will not align with each other regardless of sharing the same shape.
That's good, compared to the nominative type systems, on that point at least!
I'm just trying to help the person I'm replying to to see more arguments in favor of dynamic systems without types, not necessarily straightly aimed at TypeScript as they mainly mentioned just types.
> You lose flexibility when suddenly everything is locked to each other by name. Even if Account and Person both has a first and last name fields, you can't use both of them if the function is expecting a Account and only use the first and last name. Then you need to add an interface, name it something, then make Account and Person be based on that. Now the function is locked to the interface, and so on
I see this argument frequently, and it doesn't make sense to me. Take the following function below in JavaScript and Typescript:
function fullNameUntyped(obj) {
return `${obj.firstName} ${obj.lastName}`;
}
type FirstAndLastName = { firstName: string, lastName: string };
function fullNameTyped(obj: FirstAndLastName): string {
return `${obj.firstName} ${obj.lastName}`;
}
In both cases, the function's argument is bound to the interface represented by FirstAndLastName. The difference is that TypeScript allows you to be explicit about it and can statically determine if your code conforms to this. Without static type checking, you're implicitly bound to that interface.
Also, you seem to have a misunderstanding. TypeScript is Duck-typed. This means that interface compliance is based on structure, not name. So the following code is correct and type-safe:
class Person {
personId: number;
firstName: string;
lastName: string;
constructor(firstName: string, lastName: string) {
this.personId = 0;
this.firstName = firstName;
this.lastName = lastName;
}
}
class Account {
accountId: number;
firstName: string;
lastName: string;
constructor(firstName: string, lastName: string) {
this.accountId = 0;
this.firstName = firstName;
this.lastName = lastName;
}
}
interface FirstAndLastName {
firstName: string;
lastName: string;
}
function fullName(obj: FirstAndLastName): string {
return `${obj.firstName} ${obj.lastName}`;
}
let person = new Person("John", "Doe");
let account = new Account("Jane", "Doe");
console.log(fullName(person)); // Prints "John Doe";
console.log(fullName(account)); // Prints "Jane Doe";
Both the Person and Account classes satisfy the interface FirstAndLastName in structure, but they don't have to reference it at all.
> Type checking is a very basic form of testing that doesn't solve the most common, annoying and hard-to-track down bugs, logic bugs.
First of all, challenge. Types can help with logic bugs just fine, but also my guess would be that type bugs come up more often. This includes typos, using the wrong variables, incorrect function argument order, etc. But I'd like to see any reference for that kind of claim anyway.
Second of all, no one says you can't still can't write tests even if you're using TypeScript.
Types are some work up front but like any tool once you learn to use them it isn't really a hinderance on prototyping or experimenting-- if anything they make it easier for me. They also make it easier to refactor, since static analysis tools can help with many refactoring tasks as well.
Ive been using Python for +16 years. Most of that time, my development was using Vim with no sort of autocompletion or even a linter. After a few years away from Python, I'm back heavy into it, currently using 3.7. I have totally embraced type hints and automatic linting in an IDE (mostly use PyCharm, but sometimes Vs code). I was always pretty productive with Python, but type hints have made me even more productive. (It also helps that I'm currently doing green field development).
I like that they're optional and not enforced. However, I also like that my IDE visually indicates when I've violated that contract. Has boosted my effectiveness quite a bit. Ive defaulted to type hints almost everywhere, especially in any library code I write (I also try and write useful docstrings). For me, its especially important because I'm the most senior Python dev on the team, the other 5 are experienced devs, but just learning Python. Me taking the time to do the type hints and docstrings is immensely helpful to them, as they all come from statically typed languages.
That said, this is my opinion. That's what this "argument" comes down to. Arguing over opinions and tastes. Each has their own and their own reasoning. Doesn't make either side right or wrong. Id just say go in whatever direction works best for one's self or team. There's no one size fits all solution.
[parent predicts flamewar, starts one with:]
> Their reasoning is along the lines of, "I don't need a type system because I'm a professional and don't make mistakes."
Nah. Where did you get that? That's so horribly wrong, it's not even funny.
Types are one tool in the toolbox to describe a system. It is not the most powerful or expressive one. It just happens to be available at compile-time.
It catches trivial bugs, acts as documentation, helps the compiler with memory allocation.
It also is static. And that's where the weaknesses begin. A whole class of problems that benefit from domain definitions being available at runtime are clumsy to write in languages that force types on you. Not impossible, of course, but clumsy. (i.e. place-oriented programming)
To your point:
Everyone makes mistakes. The way to catch them and to prevent them in the future is not by having types. It's by writing tests.
Tests > Types > no types at all
Did you miss the part where they said "... at runtime are clumsy to write in languages that force types on you.."
That may most likely put "types + tests" at the bottom of their food-chain. And speaking of TS, since it compiles down to JS in production, it can be considered a very basic type of testing, or an advanced type of linting.
> That may most likely put "types + tests" at the bottom of their food-chain.
That is totally illogical.
If types are better than nothing, and tests are better than nothing, then how could both tests and types together be worse than nothing?
> Did you miss the part where they said "... at runtime are clumsy to write in languages that force types on you.."
No, I didn't miss it. I just disagree with it. Interpreting values at runtime is called "parsing". The parsing step exists regardless of whether the program is written in a static language or a dynamic language.
> If types are better than nothing, and tests are better than nothing, then how could both tests and types together be worse than nothing?
Ok, move it to the left by one, my point still stands: considering his goals and experience, types + tests will most likely be almost at the bottom of their food chain.
> No, I didn't miss it. I just disagree with it. Interpreting values at runtime is called "parsing".
Actually, you completely misunderstood it. It has nothing to do with parsing. Its all about design patterns, functional + dynamic language design patterns to be more specific.
1. I disagree. Perhaps this[0] will help you understand the bits you are missing.
2. I do not understand why you are so hostile. To try and understand, I went through some of your comment history, and I can see it's not just me you are hostile towards. Furthermore, you appear to have a poor understanding of how JavaScript works. For the former reason, at least until your anger issues are addressed, I don't find it constructive to continue discussion with you.
I have not yet looked at your comment history, but just looking at your comments a few lines up, that's what I've found. And the first two are your comment to someone else. Ever heard of projection? That is what you are suffering from if you cannot see that you are just as hostile as I am.
Personally, I respond in kind, so I am very much aware of when I'm being hostile. And unlike you, I never resort to cheap personal insults about the understanding or abilities of the people I engage with. That's just beneath me, my friend.
> Before I inherited the code, he told me, "I code in the terminal. I don't need IDE features because I don't really make mistakes in PHP anymore." Again, seems satirical, but not uncommon.
Went to a tech meetup group hosted at a moderate sized local tech company. The tech company had job openings, and I'd looked at a couple earlier that month. Some of their staff came to the meetup, and I got to talking with one of the 'lead' guys. I'd recently started using IntelliJ, and was talking to some others about how much more productive I was being, and it was the best money I'd spent on anything in year.
The lead guy jumped in and basically said IDEs were for wimps (more or less). If you're a good developer, you don't need an IDE - he knew everything about their codebase, was very productive, and had been for years.
My experience was the opposite - I do a lot of freelance/consulting/dev stuff - my life is jumping between projects every few months or year or so. Having tooling that helps me understand so much more about a project than I could get just from vim (for example) was so eye-opening and transformative to my way of thinking that it made me re-evaluate a lot of previous notions, habits and assumptions about development. I'd explained that using good IDEs had made me better at my craft in every conceivable way.
He just sort of shrugged and said he could understand why some people might need an IDE, but they're mostly just crutches for people who don't want to spend the time to learn a codebase the 'real' way.
I'd been interested in applying to that company, but didn't bother after realizing I would be having to work with that attitude daily.
When I first got into Node.js I went to a Node meetup and mentioned I was having trouble getting typescript set up. They admonished me, saying you don’t need that, you just need test coverage. Ok...
> Funny, I usually see type haters claiming that they don't actually make the kinds of mistakes that are fixed by strong typing.
As your typical type hater, my preferred argument is: yes, static typing prevents a certain class of bugs from happening; no, this class of bugs is not nearly as relevant as type lovers seem to be claiming. By an order of magnitude if not more.
Source: 6 years of being a core developer of a front end framework consisting of 1,500,000 lines of ES5 JavaScript and SASS.
I'm sure that class of bugs is relevant for Typescript programmers, because they never develop the skills to not implement those bugs in the first place.
If your usual workflow is to defer all of the typing information to the IDE, rather than keeping it in your head. Then the second you can't access that information at a whim, you're fucked. It's like how I can't navigate around my city without Google Maps, because I've never had much of a reason to.
That metaphor works well, because Google Maps is probably a net positive. It's just that if I go around waving my phone in the face of a 60 year old cab driver that knows where everything is, going "I can't understand how you think you can get around without GPS, you're making loads of mistakes without realising it", I'm going to look like a fucking moron.
> If your usual workflow is to defer all of the typing information to the IDE, rather than keeping it in your head. Then the second you can't access that information at a whim, you're fucked.
This is just not at all how it works in practice. You still keep it all in your head, but the compiler errors protect you from small mistakes.
No matter how great of a programmer you are, you will make transcription errors with the things you have in your head. This is literally exactly the type of "I don't make mistakes" nonsense that I said was common, and a bunch of other people said was extreme and a strawman.
Your argument is the one that's a strawman. You're assuming that the kind of mistakes that I make while coding are the exact kind that Typescript prevents. Which is not the case.
There's more ways than type hints to fail fast. I'm not saying me and all the other JS devs don't make mistakes. I'm saying the mistakes we make are ones that we catch in 5 seconds because the modern web dev environment is set up to facilitate that. Typescript devs make additional mistakes on top of that beacuse they have tools that catch those mistakes quickly too. We don't, so we get conditioned to program in a way to prioritise not making those mistakes (possibly at the expense of other mistakes becoming more common).
The point is that someone with years of JS experience is going to be more productive with JS, and someone with years of TS experience is going to be more productive with TS. I'm not saying Typescript sucks, just that the cost side of it's cost/benefit equation isn't the same for every dev, whereas your shit argument assumes that it is because you only base it on your own experience.
> You still keep it all in your head, but the compiler errors protect you from small mistakes.
It is interesting how "protecting from small mistakes" is touted as "solving our API woes", innit?
At some point it is liberating to admit that static vs dynamic is a matter of personal preference and nothing more. If I like it, I will find a thousand reasons to justify it, and vice versa.
I just wish everybody would be open about it: I like "type safety" and the warm fuzzy feeling it gives me, and nothing you unwashed heathens can say about tight coupling, increased incidental complexity, over-engineered APIs and productivity loss can sway my opinion! Why, my productivity is _increased_ with static typing, because I make up for hours of bikeshedding about which type better conveys the underlying intent with writing less null checks and unit tests! Take that, type haters!
> I'm sure that class of bugs is relevant for Typescript programmers, because they never develop the skills to not implement those bugs in the first place.
This rings true, especially given that in my experience, most of the static typed people either never worked with dynamic languages at all, or converted from dynamic to static. Most of the dynamic minded people I know actually converted _from_ static typing after doing that for years (myself included).
The calculus is pretty simple IMO: if one has mental discipline to work with a dynamic weakly typed language, not having to mess with types and compilers is downright liberating: ye godz, just gimme that data! On the other hand the people who never experienced conditions leading to developing said mental discipline tend to abhor the idea of not having the "type safety" (cute marketing, that). Hence the chasm between Lisp crowd and Haskell mob, with JavaScript being the perpetual battleground somewhere in between.
Ext JS is the framework in question. The last time I worked on it (Oct 2018), it was about that size shared between two major versions: Classic toolkit and Modern toolkit, including tests and examples. It could be more than that now but I haven't touched it since.
I used to do a lot of things on it, including _very_ deep refactorings with sweeping changes across the codebase. The secret sauce is focus on automated testing: when I left the company, we had ~70,000 test specs for the framework, and the test suite was executed on each commit to every PR pushed to Github. Depending on framework version (there were several in flight), and browser matrix (15+ supported browsers), each test run yielded 500,000-700,000 spec results (and finished in under 20 minutes).
There was a lot of custom tooling around this, of course. Including a test runner that I got open sourced right before leaving the company: https://github.com/sencha/jazzman. Sadly it looks like there were no new commits since I left; I hoped to pick it up later but so far I haven't encountered the need to run significantly sized test suites in massively parallel fashion. Nobody writes that many tests. :)
A framework is usually the foundational code for an app, for sure. In this case it was a bona fide JavaScript framework, Ext JS.
It is that big because it implements a lot of things that other frameworks don't even try to try thinking about, things mostly used to build very boring line of business applications (think thousands of forms, huge grids, reports with charts, etc). Applications built with Ext JS can easily dwarf the framework itself; the biggest I've seen personally was ~30 mb of minified ES5 JavaScript.
Those would be the assembly-language-coding type haters. They can't make those mistakes, or they are borked.
I make the mistakes that are "fixed" by static typing quite regularly, but since I execute the code that I write, they don't survive.
Where static typing helps is the refactoring. You change some code; what other things have to change, where?
Although informing the process of refactoring, static typing, at the same time: (A) puts up some barriers against refactoring and (B) creates the need for a lot of the refactoring in the first place and (C) requires a more complete refactoring job than is minimally necessary to validate the idea behind the refactoring.
Refactored code doesn't escape the need for testing test. If you have some statically typed code that isn't tested well, and think you can refactor it just by making a few changes and then adjusting elsewhere to shut up the compiler, you have another thing coming.
I refactor code with dynamic types all of the time with no problems -- but the code I work on has a lot of tests (or I'll add them), and I definitely never refactor code that lacks tests, whether it has dynamic or static types.
It's almost as if different people have different working styles that make different aspects of a language useful.
I think the more nuanced point folks tend to make is that they catch the errors at Run Time instead of Compile Time, and that the cost of strict typing is greater than that of catching it at Run Time.
Personally, I'm agnostic (I make mistakes in all phases and fix most of them eventually ;) )
I agree that people make that point, and I agree that it's a good one. But it's irrelevant to this sub-thread, which started with me attempting to convince smt88 that they were misrepresenting the opinion of the people they were laughing at.
Really look at any significant benchmark or what types of projects use which languages. The evidence is extremely clear and makes sense due to how computers work.
The factors affecting program speed are numerous, and I would guess that types do not have nearly the greatest effect.
Most of us are not optimizing for program speed. Machine time is cheap. Human time is expensive. The biggest cost-savers for most programmers will be the ergonomics of a language, not the optimizations available to the compiler.
That was certainly true in 1990. The use of JITs has changed that to a large extent, as frequently used code paths can be rewritten at runtime in many cases.
Static types tend to push people towards copy-pasta code, as well, which can even work against performance.
That's the first time I heard that any language that doesn't have types, is slower than a program with types. I'm unsure if that actually makes sense.
You mean slower as in performance? I'm having a hard time understanding how types == performance, so you have to mean something else.
I guess assembly would be the language you would use if you really need to squeeze out the maximum amount of performance of a single CPU, and as far as I know, it does not have types.
Also languages built on top of LLVM could get by with trading compile times for run time performance. Maybe you meant compiling gets slower without types?
Strong typing means that at runtime dynamic behaviors don't need to be accounted for.
For a compiled language, the compiler could know that `foo` and `bar` are 32-bit integers, and thus compile `foo + bar` to call the addition function for 32-bit integers. In an interpreted language, the interpreter could do the same thing.
Without that typing information, both would have to invoke a generic addition function that detects the types of its arguments at runtime, notices they're both 32-bit integers, and delegates to the corresponding addition function.
Of course there are tricks that can be played in the weakly-typed case, like assuming the same call site will always have the same types, so that there can be a short path that assumes that and only branches rarely. That way the first or first few executions might be slow, but eventually they get almost as fast as the statically-typed case. JS engines in particular and JITted runtimes in general usually do this.
>I guess assembly would be the language you would use if you really need to squeeze out the maximum amount of performance of a single CPU, and as far as I know, it does not have types.
Assembly absolutely does have types. The addition function for 32-bit ints only operates on 32-bit ints, and is distinct from the addition function for 64-bit ints.
Dynamically typed languages still have types internally, they just look like this [0] (imagine it all implemented in assembly, without C's types, if you prefer).
Types are information about the code which enables compiler optimizations, so statically typed languages generally can be faster than dynamic languages. They aren't, always, of course, and other factors come into play.
Yes, absolutely a language without types is slower. Performance nowadays is almost always due to memory access patterns and allocations. Dynamic languages not only do not often have enough information to properly allocate memory in an efficient layout but they also tend to allocate a lot overall. Assembly is generated by languages that are compiled natively or on the fly for JIT languages. The type info is used to generate more efficient assembly.
You say this sarcastically, but every JS-related thread on HN turns into a flamewar between type lovers and haters.
The type haters make exactly the argument you're mocking: that typeless languages do not result in more type errors. Their reasoning is along the lines of, "I don't need a type system because I'm a professional and don't make mistakes."
That sounds laughable or like an exaggeration, but it's a surprisingly common line of thinking. The buggiest code I ever worked on was a PHP code base written by someone who had been coding for 20 years and had a Master's in CS. Before I inherited the code, he told me, "I code in the terminal. I don't need IDE features because I don't really make mistakes in PHP anymore."
Again, seems satirical, but not uncommon.