32 Reasons WHY TS IS BETTER Than Go

Поділитися
Вставка
  • Опубліковано 28 вер 2024
  • Recorded live on twitch, GET IN
    / theprimeagen
    You Like Melkey? GIVE HIM A FOLLOW:
    / melkey
    / @melkeydev
    Reviewed Reddit post: / anyone_who_tried_to_li...
    By: simple_exporer1 | / simple_explorer1
    MY MAIN YT CHANNEL: Has well edited engineering videos
    / theprimeagen
    Discord
    / discord
    Have something for me to read or react to?: / theprimeagenreact
    Hey I am sponsored by Turso, an edge database. I think they are pretty neet. Give them a try for free and if you want you can get a decent amount off (the free tier is the best (better than planetscale or any other))
    turso.tech/dee...
  • Наука та технологія

КОМЕНТАРІ • 559

  • @roccociccone597
    @roccociccone597 Рік тому +301

    As so often is the case... The guy in the article tries to write TS using Go. If you want to write TS then use TS. Go is great but not if you treat it like TS.

    • @ryangamv8
      @ryangamv8 Рік тому +12

      No immutable variables tho. Tf is up with that

    • @roccociccone597
      @roccociccone597 Рік тому +5

      @@ryangamv8 yeah sometimes it would be nice. Constants can cover some of those cases but since they're compile time constants they're not the same unfortunately. It would be nice if they introduced that eventually.

    • @gilbertovampre9494
      @gilbertovampre9494 Рік тому +15

      Or any other language, I’m tired of people trying to write Java, C++, JS and other stuff in Go. You look at the code, you see the mess, you think “this looks like this person is trying to write in X language”, and than you go check their background and as it turns out, in their previously job they were writing in X language, you can see it right through it.

    • @cranberry888
      @cranberry888 Рік тому +2

      ​@@gilbertovampre9494how Go style different from x language?

    • @gilbertovampre9494
      @gilbertovampre9494 Рік тому

      @@cranberry888 like, when I see "IRepository", "IClient", etc. or getters and setter for everything and everywhere, named "GetThis", "GetThat", they all came from some OOP language like C# or Java. When I see too much reflection or Generics, they probably came from JS, and so on. I might be wrong, I'm just stating about my own experience, and to this day it was never wrong. It's just minor things that give up their background.

  • @Speykious
    @Speykious Рік тому +145

    As a Rust programmer, the one thing I dont like in Go's error handling is that you can still technically access the value even if there's an error. You get both the error and the value at the same time returned. In Rust you're guaranteed to only get one or the other thanks to ADTs.

    • @krux02
      @krux02 Рік тому +37

      It has been repeated 1000 times. Yet as a go programmer, it doesn't bother me, or cause any bugs. I had to get used to it, sure. But after that it's just smooth sailing.

    • @Tresla
      @Tresla Рік тому +39

      ​@@krux02 The issue is that it CAN cause bugs. Not to mention, not every function follows the rule of "if it returns an error, the value should be regarded as invalid". And it's not always clear without reading through all of a function's documentation (io.Reader is a perfect example of this). I've been programming primarily in Go for the past 7 years, and can say with confidence that Rust's way is just plain better.

    • @johnyewtube2286
      @johnyewtube2286 Рік тому +33

      "as a ___" why do people feel the need to state they are writing as something or other? Is it just readit brain?

    • @deformercr6680
      @deformercr6680 Рік тому

      ​@@johnyewtube2286it helps the reader gain perspective about where someone might be coming from.

    • @SimonBuchanNz
      @SimonBuchanNz Рік тому +44

      ​@@johnyewtube2286because it informs you of why they're saying the thing they're saying?
      You might have had a point if you saw "as a hair dresser, I think roundabouts are better than lights"

  • @ntrrg
    @ntrrg Рік тому +11

    25. A slice is a portion of an array (which may be the whole array if you do x := [5]int{0, 1, 2, 3, 4}; s := x[:]). They work on top of the array you slice. Mutating a slice element (s[0] = 5), will mutate its backing array (x[0] is also 5 now), and those changes will be reflected on any slice from that same array, if you need a copy, you have to use the builtin copy functiom or make a copy manually (for loop and copy to new slice with a different backing array, for example).
    Slices are passed as copy, but it doesn't mean you will get a full copy of its elements, you just get a copy of the slice data structure, which is a struct { length, capacity int, data uintptr }, but data is still a pointer, so if you do s[0] = 0 inside a function, it will mutate its backing array. If you pass s to a function, and do s = s[1:], s is now [1 2 3 4] in the function scope, but it will still be [0 1 2 3 4] outside the function.
    I actually find it quite easy to understand, and I am pretty stupid, its like any user defined data structure would behave when it is used as argument in Go. There are some other rules like appending to a slice with not enough capacity, but once you know the rules about slices, it is easy and makes sense.
    P.S. having unmutable data structures in Go is not possible, you can make copies, but mutating it is not a compile error.

    • @a-yon_n
      @a-yon_n Рік тому

      It took me a very long time to understand slice and yet I don't think I have fully captured it. Currently I see it as a view of the underlying array, when we cut a slice, we just create a new view of the same array, so manipulate one of the views will affect all the other views. It's so silly that Go designed it this way, make something very simple so hard to understand.

    • @ntrrg
      @ntrrg Рік тому +1

      @@a-yon_n I think sometimes we overcomplicate some concepts, in simple words, arrays are static arrays and slices are dynamic arrays.

    • @Nenad_bZmaj
      @Nenad_bZmaj 7 місяців тому

      You have to be careful when appending to a slice within a function, if you want to observe that change in the caller function. If the capacity is exceeded, the slice inside the function will start pointing to a new array which is a copy of the old array but with double capacity. The original array remains unchanged and at the same old address, at which your outside slice points to. Thus you won't see the change.
      In that case pass the pointer-to-slice, instead of the slice. It points to the address of the slice header, not of the array, and so any change within a function works on the slice residing in the caller.
      Also consider this: you pass the instantiated but empty slice 'a' to a function which should populate it, and suppose your function makes slice 'b' with some elements, or calls another function whose return value is equivalent to slice b. And you just assign: a = b or a = g(...) (function g returns a slice).
      Now, slice 'a' inside the function (and, of course, inside the function that slice can have a different name i.e. the name of the parameter, but we tend to use the same names for arguments and parameters) - points to the underlying array of b, but the slice a in the caller still points to the same empty array as before.
      In that case, also, pass the pointer-to-slice to the function parameter and assign like this: *a = b, since by 'a' now you call a pointer variable, so you deference it to get to the slice header in the caller. And now slice in the caller points to the underlying array of b. You didn't have to copy each element in a loop. Also use *a = append(*a, c...) when appending inside the function, slice 'c' to slice a in the caller and you are not absolutely sure that you won't exceed capacity at runtime.

  • @jonasstrmsodd6352
    @jonasstrmsodd6352 Рік тому +22

    I think I just like Go now. The whole try-catch blocks in TS is a nightmare, and I'm fairly sure it nudges you towards just "YOLO: Hope it doesn't fail".

  • @MassimoLuna-o4r
    @MassimoLuna-o4r 3 місяці тому +1

    I love getting a new perspective on things, although I don't think you are always right about everything. I feel like it takes great courage to stand in front of this many people and state you opinion and I admire you for it. - No matter if it is factual or aligns with my views. Thank you. Keep it up :)

  • @LusidDreaming
    @LusidDreaming Рік тому +7

    Just a quick PSA, accessing JS object fields by variable is a security vulnerability if that field can be defined by user input.

    • @aimanbasem
      @aimanbasem Рік тому

      by the same token, indexing a list with a variable is also a vulnerability, isn't it?

    • @LusidDreaming
      @LusidDreaming Рік тому +2

      @@aimanbasem if there is no bounds checking, which i believe there is in JS. But in C there is no bounds checking so if an array can be indexed arbitrarily (or even just access OOB), there are ways for a user to take control of the program and start trying to execute OS commands with whatever access the program was given. This is also why you should assign specific users/roles to processes and never run them as root unless absolutely needed

  • @oakley6889
    @oakley6889 Рік тому +12

    Functional overloading exists in alot of langs, and its quite useful. Im pretty sure c++, java, a good handful of functional langs, etc
    Its good if you have some optimisation that uses a lookup table or premade collection that needs to be searched, if its created before, it can be passed in, or the function does it itself

    • @tokiomutex4148
      @tokiomutex4148 Рік тому +10

      The only thing function overloading is good at is making the code more confusing, change my mind!

    • @Ryuuzaki145
      @Ryuuzaki145 Рік тому

      ​@@tokiomutex4148 with proper naming, I'd disagree. The method "String.toString()" in C# has many overloaded methods that still does exactly what the function means, the algorithm just is different depending on what data type is converted into a string.
      Building multiple constructors is also great, but you could argue we could simply create an empty constructor first then chain set properties to accomplish the same goal (such as " New Object().property1 = value
      .property2 = otherValue
      .property3 = value3; )
      I find that function overloading only makes sense in OOP though. In Go, it would feel weird, kind of out of place

    • @atiedebee1020
      @atiedebee1020 Рік тому

      ​@@tokiomutex4148and they cause name mangling...

    • @edoga-hf1dp
      @edoga-hf1dp Рік тому +3

      Function overloading can be good for optional arguments or handling of same functionality for different types

    • @tokiomutex4148
      @tokiomutex4148 Рік тому +3

      @@edoga-hf1dp Until someone modifies the code and a different definition of your function ends up called, good luck debugging it!

  • @Daniel_Zhu_a6f
    @Daniel_Zhu_a6f Рік тому +11

    function overloading is a good alternative to OOP and object.verb(subject) notation. overloaded function call is essentially pattern matching on a tuple of types. so it's a good option to have

  • @thinhle462
    @thinhle462 Рік тому +6

    For number 7 and your example, i would use json instead of map. In number 14, we could utilize struct and pointer to construct a optional value parameter or u can say dto

  • @davidsaint8866
    @davidsaint8866 9 місяців тому +2

    for point 7, I think it's better in GoLang, as they can pass variables that don't exist in your struct.
    What I do in that scenario is create a function, loop through the filters and have a swith case statement that handles the supported properties, and a default. It's a bit more work, but it ensures the integrity of the system is not compromised.

  • @codeChuck
    @codeChuck 7 місяців тому

    @ThePrimeTimeagen, your point is very valid! If function signature in ts accepts a union type of arrays, it will be a runtime error in js!
    So, before pushing something into an string[] array, you should check for argument type to be a string with typeguard: ```ts if (typeof arg !== 'string') return; ```

  • @Nenad_bZmaj
    @Nenad_bZmaj 7 місяців тому

    #26 - slices are NOT messy if you first read the language specifications. A slice holds three numbers: memory address, len and cap. The first one is a pointer to an allocated array. That address is the VALUE of the slice. In assignments to other slices/new slices, as any other value, it is copied, thus the memory address of the underlying array is copied. Therefore, all slices derived from one slice point to the same array UNTIL YOU CHANGE their value.
    Example. a := []int{1,2,3}. There is an array holding 1,2 3 and some more space where you can append new elements. Now, b:= a. b points to the same array. c:= b[1:] . c points to the same array but starts at index 1 of b, so it represents 2, 3 elements. e :=c[1:]. e represents element 3, because it starts from index 1 of c. You can't retrieve the leading elements, i.e 1, 2 (as you can with tailing elements), but you still have slice a if you need them.
    But let's have d:= []int{1,3,5.7}. This points to another array. Now lets assign: c = d[:len(d)-1]. Since value of d (memory address of the second array) is assigned to the value of c, c NOW DOESN'T POINT TO THE FIRST ARRAY but points to the second array and represents numbers1,3,5 , but last element is sliced away by slice operation. You can retrieve it: c= c[: len[d)].
    Just as with x:=3 , x changes its value when you assign x=7. A slice behaves the same way, only its value is some memory address.
    Now, his objection was (probably) this: When you pass a slice to a function as value (it is still reference to an array, and thus light-weight), and use the builtin append function to append the receiver var inside the function, if the slice capacity is exceeded, Go runtime will copy the ARRAY to a new location but with a double size (new cap = 2*(old cap + num of appended elements).Of course, the value of slice inside the function changes: it now points to this new array. The slice in the caller still points to the old array and thus that array is not appended beyond its capacity.
    In order to obtain the wanted result in this case, don't pass a slice to the function, pass a pointer to slice. The receiving parameter points to the slice header on the stack of the caller function, and whatever you do with it affects that slice header, and that one, as any slice, is always pointing to its underlying array on the heap, no matter if that one was copied to another place in memory (at least until you change the value of the slice).
    OR, return the slice from the function, and you don't have to use pointer to it.
    But if your function parameter ap received &a (a being some slice from the caller), and then the function did this: *ap = c (c being some other slice pointing to a different array), then you changed the value of a from within the function, and now a points to that different array. This is perfect for populating a slice from some function that spits out the slice, all at once, and you don't have to copy element by element, UNLESS you want, for some reason, to have exactly the old array repopulated and you care about the address. In that case you wouldn't use *ap = c, but builtin copy function: copy(*ap, c). The copy function copies all elements to the underlying array of a, and the value of a (the address of that array) is not changed. In fact, in this case, you can pass a (not pointer to it) and do: copy(a, c) in the function, and you don't have to return a.

  • @LusidDreaming
    @LusidDreaming Рік тому +5

    I will say Omit type is nice for DTOs. Like I can say this DTO is the whole object except the DB generated ID, and now any time I modify the object my DTO mirrors it.

    • @mage3690
      @mage3690 Рік тому

      Oh, _that's_ what that is? Just a slice of a struct? Why isn't that a thing?

    • @LusidDreaming
      @LusidDreaming Рік тому

      @@mage3690 the only thing that is a little frustrating is the type hint will always just show Omit instead of the whole object, but it really is a really convenient feature otherwise. And it makes refactoring things easier. When you update a class, you don't have to update all the partial DTOs and you don't even have to modify much code unless the code specifically access a field that was changed.

    • @kowalkem
      @kowalkem Рік тому

      Why not use struct embedding?

  • @huge_letters
    @huge_letters Рік тому +1

    17:50 - I don't think that's really TS unions fault but more fault on the part of how TS treats mutations. I think TS type system is very "math-y" with how sets relate to each other and that's the artifact of that - Array is indeed a subset of Array, there's nothing inherently wrong with TS "thinking" that.

    • @huge_letters
      @huge_letters Рік тому

      @llIlllIIlIIlllIlllIl fair point, yeah. Cause then the operations available on set members also are a part of the set. So a mutable Array set also includes an operation .push(string). And then you have that .push(string) is not a subset of .push(string|number) but vice versa so neither Array set is a subset of each other.

  • @Josh-hv4wo
    @Josh-hv4wo 7 місяців тому

    Typia allows for runtime validaton of TS objects using TS types/interfaces. Write an interface. Validate some incoming json against it. Beautiful.
    All the other runtime validation libraries have you operate kind of backwards to that.

  • @josefnymanmuller374
    @josefnymanmuller374 Рік тому +1

    Your Zod competitor already exists, it's called Typia. It does types => validation, types => json schema, types => protobuff schemas.

  • @chrism3790
    @chrism3790 Рік тому +39

    To me, a telling sign that someone is inexperienced in programming (or that they're using the wrong tool for the job) is that they complain about error handling being cumbersome. It tells me that they haven't been bit in the ass enough times to realize that handling errors is orders of magnitude less painful than dealing with run time bugs and crashes. Go's approach to errors might not be elegant, but try/catch is 100 times worse, because it gives programmers a responsibility they're usually are too lazy to handle.

    • @felixjohnson3874
      @felixjohnson3874 Рік тому

      I'd rather the program fail than clobber itself or anything else

    • @zhamed9587
      @zhamed9587 Рік тому +2

      It turns out that it's easy to mistakingly ignore or overwrite errors in golang. I've worked on large golang code bases, and I've seen this issue many times. It's a mediocre and badly designed language at the end of the day.

    • @sergisimon9620
      @sergisimon9620 11 місяців тому

      I still feel like errors should be sum types, like in Rust with Result or Either with Haskell.
      That being said, I'm 100% on having error handling as values and that the compiler forces you to know that something can error.

    • @refusalspam
      @refusalspam 4 місяці тому +1

      Why not use Checked Exceptions like in Java. If they made it so that you had to either eat the exception or declare that your function also throws it, then the compiler can always inform you if you missed handling any error.

    • @chrism3790
      @chrism3790 4 місяці тому

      @@refusalspam Yep, many languages have this. Rust, for example.

  • @joaodiasconde
    @joaodiasconde Рік тому +2

    Errors by values is definitively the best. Rust does it better leveraging sum types to force engineers to handle the error to unwrap the value. I think what is also missing in Go is a sort of propagating the error up the callstack feature, like Rust's question mark operator. That allows the example of one mechanism to catch all and handle the same way.
    Also, yeah dead locking yourself could be argued as being a skill issue, but so could every C++ footgun and we still dunk on C++ for it... as an industry we need to push for languages with fewer footguns.

    • @dongueW
      @dongueW Рік тому +1

      Valid points!

    • @matheusjahnke8643
      @matheusjahnke8643 10 місяців тому +1

      If not every, an overwhelming majority(like, 90% or more) of language disadvantages could be compensated with skill... so technically they are all skill issues.

  • @trapexit
    @trapexit Рік тому

    @14:00 An uncaught exception is an abort()/assert(). It's pretty trivial to do that around the code if that is in fact the behavior you want.

  • @robfielding8566
    @robfielding8566 10 місяців тому +1

    what you really want is to explicitly handle all errors that are the result of a bad input, and a 4xx in all such cases. a try/catch or a panic/recover are only to handle something that got missed, that is presumed to be a coding bug as 5xx. the try/catch or panic/recover is a fault barrier. each thread should have a fault barrier at the top if it doesn't continue with a new session; or in the top-most loop as the fault barrier. fault barriers log things that got missed. reaching the fault barrier IS a bug. you can't always recover for real though. "out of filehandles", and your process can't safely proceed with anything.

    • @robfielding8566
      @robfielding8566 10 місяців тому +1

      the main thing that IS wrong with Go error handling: returning 'error' isn't specific enough. You should return the most specific type you can that has the error interface. ie: ex FileNotFound ... ex.FileName. If you are in the middle of doing a task, then that task's error should get returned. If it was caused by an error inside of that task, then that error should be used to construct that task's error. That way, you get context about what you were DOING when it errored out. It is pretty important that the task know what HTTP error code to suggest. You should return 4XX errors on bad input, and 5XX on errors deemed to be bugs to be fixed if your own code. This is why it's a bug to hit the top-most fault-barriers. It means that you missed something that was bad input, or something that could have gone wrong internally. You need to update your code so that all errors can tell you definitively whether fault lies outside the process, or inside the process.

  • @christian15213
    @christian15213 8 місяців тому

    there is definitely overloading in JS/TS. this helps with variations of the function

  • @ShadoFXPerino
    @ShadoFXPerino Рік тому +1

    25:30 * is a dangerously leaky abstraction. Option and ? are less leaky.

  • @mattymerr701
    @mattymerr701 Рік тому +1

    Constructor overloading != function overloading.
    And function overloading can be generics via syntax sugar.

  • @00jknight
    @00jknight 9 місяців тому

    In go, you can recover from panics and return a 500, or treat it basically like try/catch. It's kinda wild but it's useful to use at the root of your request handler in a http server for instance.

  • @MrToup
    @MrToup 10 місяців тому

    I really like when you take a really small snippet to explain your point. Would love to see more.

  • @Fan_of_Ado
    @Fan_of_Ado Рік тому +17

    I've had to write some TypeScript this week despite being someone who usually only does Go.
    TypeScript was pleasant BUT WTF is the difference between cjs, node, esm2014,esm2020 and on and on. The tooling also sucks. `tsc` for some reason doesn't handle imports correctly and I had to use esbuild to bundle stuff then use tsc just for the d.ts type declarations.
    I could probably spend a month learning how to use it "properly" but why must it be so painful?
    I tried bun. It was great except for the fact that the cryptography implementation is incomplete and thus I can't use `bun build`. It's meant to be a simple npm library. It shouldn't take this much effort.

    • @jhonyhndoea
      @jhonyhndoea Рік тому

      true. the ecosystem sucks. you can give Deno a shot, my favorite so far.

    • @oserodal2702
      @oserodal2702 Рік тому +2

      Welcome to the Javascript ecosystem.

    • @Fan_of_Ado
      @Fan_of_Ado Рік тому +1

      The bun developers are VERY helpful. They solved my issues with their crypto implementation in an hour

    • @Dipj01
      @Dipj01 Рік тому +1

      Almost everything has to be convoluted in javascript. Almost everything.

    • @buc991
      @buc991 Рік тому

      It’s not much effort just ppl trying to use stuff without learning anything about it first. Oh JavaScript have versions oh noo so hard 😮😂

  • @oakley6889
    @oakley6889 Рік тому +1

    People taking about elixir are actually dead on, kinda insane how much it taught me about alot of these areas

  • @kowalkem
    @kowalkem Рік тому +1

    Guy must've gotten oat milk instead of soy.

  • @joyride9998
    @joyride9998 7 місяців тому +1

    13:00 that's not really true... you can have similar construct as try catch also in go :
    func HandlePanic() {
    r := recover()
    if r != nil {
    fmt.Println("RECOVER", r)
    }
    }
    func divide(divisor int, divider int) {
    defer HandlePanic()
    if divisor < divider {
    panic("start is greater than end")
    } else {
    fmt.Println(divisor / divider)
    }
    }

  • @JOHN-um2
    @JOHN-um2 Рік тому +1

    Point 9 is invalid since json you can make a new decoder that doesn’t allow unknown fields. Therefor catching your typo.

  • @baobaobiz
    @baobaobiz 10 місяців тому

    In practice, with golangci-lint (a huge collection of validation), I feel like Go's 'security' is pretty good, a weakness that people make comparing to Rust. I have a setup using Task (makefile in Go) that runs the whole suite of checks and output good code before commit. I feel the people often compare languages based on the 'out of factory, default' DX that they provide, which I think it's valid but also not practical, when serious project are a work of engineering system with carefully setup pipelines, no one just use the default language toolings itself in real project.

  • @NuncNuncNuncNunc
    @NuncNuncNuncNunc Рік тому

    Errors are values but not the desired value so this sounds like a use case for Either. If you use Either and pattern match on the result you will always handle the error assuming unhandled cases are treated as errors.

  • @ShawnPMurphy8
    @ShawnPMurphy8 11 місяців тому +1

    Ok I have tried and tried to figure out what the actual problem is with the CrappyUnion complaint around 17 minutes in. Can someone please enlighten me? IMO it does precisely what I would expect. The parameter of the function takes in an array of type CrappyUnion which means the array can be a mix of strings and numbers or all strings or all numbers. You are guaranteeing nothing other than the fact the array has to be made of items that are either a string or a number.
    So when you then pass in “a” to the function, it is an array of all strings…. that satisfies the requirement for the parameter type of CrappyUnion[]… so what is the problem?
    Can it be a little weird working with an array like that? Yes I agree, but that is more of an implementation/design issue than a TS Type system issue. That example also isn’t really practical IMO having a parameter with an array type of string or number but then all you do is push a number to it. In that simple scenario the issue is the parameter should just be number[] given that is all the function needs. And yes if you added another push of a string in the function you could say now it needs the union type of string | number for the array but I would argue that is just poor design then. First off to me this scenario would be a bit of a code smell as a mutability issue passing that string array in like that to a void function without a return. I think a more typical realistic pattern would be setting a = to return of the function which at that point then it would indeed give you a type error because it would know “a” is a string[] but the return of the function would be a (string | number)[] … OR if just using the specific simple example and it returned the array after just pushing a number, it would return number[] which would obviously also cause an error during compile / transpile.
    TLDR: to me that is a bad implementation example along with the fact mutating an array with a void function is an anti pattern in my opinion 🤷🏻‍♂️
    This is kind of like the parseInt() example later in the video where yes you can create some weird scenarios to prove a point but it shouldn’t be used as a qualifier for whether a language feature is good or not when in reality it is more of a quark or idiosyncrasy than a bug or bad feature.
    But I would love it if someone enlightened me if I am just wrong or missing something?! 🤷🏻‍♂️

    • @ShawnPMurphy8
      @ShawnPMurphy8 11 місяців тому

      Typed this original comment on my phone yesterday which is why no real code examples and potentially was a bit confusing, but ultimately here is my point... this is the way I would write this code in the first place (assuming it was a legit use case / example) given the function will be mutating the "a" array. You will then get a TS Type error:
      ```ts
      type CrappyUnion = string | number;
      let a: string[] = [];
      function addToCrappyUnion(b: CrappyUnion[]) {
      b.push(123);
      return b;
      }
      a = addToCrappyUnion(a);
      // TS Error: Type 'CrappyUnion[]' is not assignable to type 'string[]'
      ```

  • @nexovec
    @nexovec 4 місяці тому

    OP: "Why can't you be like typescript?"
    Go: "I'm sorry, dad"

  • @Nenad_bZmaj
    @Nenad_bZmaj 7 місяців тому

    #5 - "x implements Method1 and Method2" sounds like the repetition of obvious to me. I guess some confusion might arise when assigning a var to an interface (or putting it as an argument to a function whose parameter is an interface, which is the same as assignment). But then, the compiler will tell you if you made a mistake and why.
    In the following example it is easy to see that y implements only addOne() method and thus implements both myInt and myFloat types, because they both have that method. On the other hand, x must implement two methods (more restrictive), so it only implements myInt, which is the one that has both of these methods.
    Thus, if I try to assign: x = &f, I'll get the following clear response from the compiler: "cannot use &f (value of type *myFloat) as incdec value in assignment: *myFloat does not implement incdec (missing method subtractOne)", although I would phrase it: "myFloat is not implemented by incdec".
    BTW, why would you have to go over declarations if you work in IDE? Just type . or . and you'll get the list of methods.
    package main
    import "fmt"
    type (
    incdec interface {
    addOne()
    subtractOne()
    }
    inc interface {
    addOne()
    }
    )
    type (
    myInt int
    myFloat float32
    )
    func (n *myInt) addOne() { *n++ }
    func (n *myFloat) addOne() { *n++ }
    func (n *myInt) subtractOne() { *n-- }
    func main() {
    var (
    n myInt
    f myFloat = 1.2
    x incdec
    y inc
    )
    x = &n
    x.addOne()
    a := n
    x = &a
    x.subtractOne()
    y = &f
    y.addOne()
    y = &n
    y.addOne()
    fmt.Println(a, n, f)
    }
    Output:
    0 2 2.2
    In the next example, there are slices types: Ints, Floats and Strings. All three have method App attached to them, so they all are implemented by AnyAppender interface (only App method). Only Ints and Floats also have method Inc, and so the interface NumAppender (App and Inc methods) implements those two types but not Strings. See go.dev/play/p/J9FEKP6NvJF

  • @darvoid
    @darvoid 11 місяців тому

    JSON thingy hint: use yaml string tags `yaml:",inline"` and you never miss a object key :'D and you can use yaml tags for json xD (I kinda find this silly xD but works)

  • @TahirDibirovII
    @TahirDibirovII 27 днів тому

    All we need is seperate AOT to machine code compiled engine for TS. Someone please invent this shit!

  • @soggy_dev
    @soggy_dev Рік тому +1

    Very much on the go team. Just wanted to point out that function overloading is absolutely a thing in TypeScript and I'm fairly certain it actually came from JavaScript. Been writing odin recently, and their approach to overloading has been super convenient and I kind of wish go had it

    • @majorhumbert676
      @majorhumbert676 Рік тому +1

      Overloading is completely unnecessary. Just create two different functions.

    • @Gusto20000
      @Gusto20000 Рік тому +1

      #define true false 😂

  • @arnerademacker
    @arnerademacker Рік тому

    This was basically programming slander in all directions for like an hour and I love it

  • @christian15213
    @christian15213 8 місяців тому

    Agree, there are pros and cons for both languages. You can do functional programming in TS and vice versa in GO.

  • @nyahhbinghi
    @nyahhbinghi 7 місяців тому +1

    Go is bad *BUT* receiver methods are great because (1) avoid need for `this` and (2) methods don't need to be bound to receiver, they are pre-bound

  • @nenadvicentic
    @nenadvicentic 9 місяців тому +1

    You guys completely missed the point about difference in exceptions in Go and TypeScript.
    Errors in Go do not stop program execution, which is completely crazy. That is THE difference.
    In any normal/sane language errors stop the execution. In TypeScript, as an example of such language, you put try/catch when you have "expected exception" and want to continue execution, which is fairly rare case (>5%?). While in Go, in order to stop execution, which is 95+% situations, you have to handle it manually.
    And people who are writing try/catch blocks all over the place... they are doing it wrong way.

    • @ThePrimeTimeagen
      @ThePrimeTimeagen  9 місяців тому

      Simply disagree
      Errors are values

    • @nenadvicentic
      @nenadvicentic 9 місяців тому +1

      @@ThePrimeTimeagen And when your function returns int 0, because of an error, you code should simply continue running and threat your 0 as result from calculation?

    • @Nenad_bZmaj
      @Nenad_bZmaj 7 місяців тому

      @@nenadvicentic Errors are not some random thing, they have causes which you, as the code author, must be able to anticipate and handle in advance. Errors in calculation are not acceptable. You'll discover bugs by testing, bugs are not errors. Aborting is not graceful. Warning the client side and leaving them options to change parameters or exit, is.

    • @nenadvicentic
      @nenadvicentic 7 місяців тому

      ​@@Nenad_bZmaj Half of your reply is stating exactly what I am saying and other half is contradicting it.
      Errors can be expected (once you can anticipate) and unexpected (e.g. random hardware or network failure). Do you think your code should "continue on unexpected error" by default? I think it should throw by default. And BUBBLE. And if you want to provide user with options after error, you do try/catch on top, user interaction level. Not on every intermediate level, just to re-throw it up. That is anti-pattern and that is what Primeagen constantly throws in as an argument against try/catch.
      Regarding calculation, parts of data you calculate on, or pre-calculated partial, come from different data sources or a different server. What if IO fails while reading the subset of the data? You catch that with unit-tests? You "continue by default" defaulting, let's say `int` to default 0? This is an argument to say that in 90%+ of use-cases we want code/runtime to throw on unexpected error, not to continue. Therefore, language/runtime defaults should cover 90% use-case, not 10% use-case.

    • @Nenad_bZmaj
      @Nenad_bZmaj 7 місяців тому

      @@nenadvicentic To be honest, I have zero experience in any language other than Go, but I very much like the way I can handle errors in Go, because I feel I am in full control and there is no magic or black box that I have to rely upon.
      In your example, one should always anticipate reading failure. Each os or io function returns errors as values and they should be called that way. Your function that calls reading a file should not abort the whole application, but back propagate the error to the caller. It is up to the overall design at which level the caller decides what to do with that error, say, request data to be sent again before proceeding with calculations.
      You know what data structure you expect and the nature of the data, so you can also check the data integrity (in case reading was successful) and your function that does this check should return error as value.
      But even in the case you mentioned, unsuccessful read will not generate zeros in place of missing data - there will be no bytes at that place (you'll also get the returned number of bytes read). So, if you decide to not handle that error, in the next step, when accessing that missing spot, you'll get panic anyway, so the program does abort. I just don't like that, so I'd handle panic as well at some higher caller level to be able to finish gracefully.
      To be more precise: you have a slice of int32 and it holds N elements, so you expect to read 4*N bytes. But the read was unsuccessful and only 12 bytes were read. What you were saying is that only first 3 ints were populated but the rest remain zeros and the program continues. But that is not true. You have to have a function that converts bytes to int32 and that function ranges through the slice of int32. When it comes to index 3 it wants to access the byte slice at offset: 3*4 , i.e. the 13th byte. But there is no 13th byte in that slice, so program panics with "out of range" if you chose to ignore the reading error.

  • @waffles3782
    @waffles3782 Рік тому

    A good use case for [8] that was explained to me was say, creating a new entry in something.
    For example a user obj/struct that has fields for name, email address, phone number and a unique ID. When adding a new user, you might not have an ID yet, that could be automatically assigned from the DB, so your create user gets filled out as a (not the right syntax, but whatever).
    So this way when the User type gets more fields added to it in the future, your adder still needs to be modified to support that because it's linked through.
    Whereas having two versions, effectively UserWithID and UserWithoutID means there's no linking and you have to remember to add/remove fields in both whenever it changes.
    I guess the alternative is having inheritance maybe? But fuck that.

    • @Luxalpa
      @Luxalpa 10 місяців тому

      Yes, this is what I'm missing as a Rust developer. I really enjoyed composing the types in Typescript even though it was quite hard at times. But in Rust I need a variation of similar types (think of builder pattern for example) and it's a hassle!

    • @Nenad_bZmaj
      @Nenad_bZmaj 7 місяців тому

      In Go, you can embed struct as a struct field:
      type(
      UserData struct {
      ID string
      somethinElse int
      }
      User struct {
      name string
      email string
      phone string
      otherData UserData
      }
      )
      //In func :
      var (
      usrDatas []UserData
      users []User
      )
      //For index i:
      user, usrData := new(User), new(UserData)
      user.name =
      usrData.ID =
      user.otherData = usrData
      users = append(users, *user)
      usrDatas = append(usrDatas, *usrData)
      //
      //updating:
      users[i].otherData = usrDatas[i]
      You access users[i]'s ID by: users[i].otherData.ID

  • @uszeyboi
    @uszeyboi Рік тому +1

    36:38 isn't that a polymorphism?

  • @R4ngeR4pidz
    @R4ngeR4pidz Рік тому +1

    Hey! I'll have you know I like living under my stupid rock, thank you very much

  • @emjizone
    @emjizone Рік тому

    0:01 @ThePrimeTimeagen, About that stupid rock, there's no "under" or "over" in space.

  • @kakwa
    @kakwa 11 місяців тому

    1 reason why a balance article is better than any article entitled "N reasons why X is better than Y".

  • @kahnfatman
    @kahnfatman 11 місяців тому

    The TS guy has not been thru hell -- he thought Satan is throwing him a party there.
    The only inheritance you may desire is that which from your great grandpa: The clock. But if you love your great grandma, you would rather borrow his books in your composition :D

  • @emeraldbonsai
    @emeraldbonsai Рік тому

    hearing how go handles errors and i realize thats exactly what i use rust for i just use match to then set a variable to a err json output XD

  • @bilbobeutlin3405
    @bilbobeutlin3405 Рік тому

    What watch is Melkey wearing?

  • @vedantmatanhelia1016
    @vedantmatanhelia1016 9 місяців тому

    With reference to point 8 can't u just make a var struct (temporary struct) that contains the filtered fields and paase that around

  • @mage3690
    @mage3690 Рік тому

    What's not to like about Go? The colon-equals? Fair enough, I don't like that either. That's a whole extra two keypresses every time I set a variable.
    No ternary operators is a _good_ thing. If you're stacking ifs that deep, just use an if statement to set a variable that you can use as an rvalue in the next if. My first officially taught programming language in tech school was ladder logic, a dataflow language. I was always trying to stuff more logic into every box (or rung, because ladder logic is primarily written in rungs). I'd ask my prof how to stuff more logic onto a rung, he'd come over, stare at my colossal mess with an expression of horror and confusion, and tell me "if it's that complicated, set a variable." Naturally I didn't want to, stuffing a procedural mindset into a dataflow language is an exercise in futility, but it taught me to seriously think about why I needed that much logic, and to make my code more readable. If there's one language that will make the most trivial code unreadable if you're trying to do it wrong, it's ladder logic.

    • @justsomerandomguyman
      @justsomerandomguyman Рік тому

      Nah, you should research the difference between expressions and statements and try to better understand how expression oriented programming is better.

    • @mage3690
      @mage3690 Рік тому

      @@justsomerandomguyman just because you want to use functional programming for concurrency doesn't mean you can't use imperative for creating memory. Matter of fact, I think programming in general would go so much better if everyone just did that: imperatively create all the memory you need, then functionally edit that memory as inputs come in. Let each tool do the thing it's good at without being dogmatic.
      Also, the idea that somehow an extra colon in my variable initialization makes a language better is just goofy to me. I guarantee you the compiler could trivially know where that colon should go even if I never specified it. Unless you're shadowing a variable, there's no point. And if you are, well, IMHO that's bad practice anyways: the language should just assume scopes inherit everything or nothing from the scope above them and go with that. In this one area, be more like PHP. Assume nothing, at least for function scopes, and force programmers to declare side effects.

  • @DexterMorgan
    @DexterMorgan 10 місяців тому

    After watching this video I'm convinced that Prime is the reincarnation of the original Menace.

  • @KevinCaffrey
    @KevinCaffrey Рік тому +3

    In Go, the equivalent of “implements XYZ” is “var _ XYZ = (*MyStruct)(nil)”. A bit clunky, but does just about the same thing as an “implements”.

    • @white-bunny
      @white-bunny Рік тому +2

      Interfaces are intrinsic. You're not supposed to write implements in the code, Go is supposed to find that out itself.

    • @KevinCaffrey
      @KevinCaffrey Рік тому +1

      The pattern I described can be found in Go’s FAQ. Sure, it’s not necessary to have such a statement, but it can’t be that unidiomatic if it’s in the official documentation. I find that it can be useful in certain scenarios, providing a helpful guard rail when I refactor interfaces.

  • @awokawok8453
    @awokawok8453 Рік тому

    11:29 did he just V> instead of >>? what a war crime, inefficient, and blazingly slow keybinding

  • @GRZlllBadman
    @GRZlllBadman Рік тому

    make a video sir about how to handle errors

  • @Friskni
    @Friskni Рік тому

    isnt your zod alternative just ajv?

  • @antonpieper
    @antonpieper Рік тому +1

    17:33 The problem is that typescript by default does not distribute the union members for array declarations. So `CrappyUnion[]` turns into `(string | number)[]` and *not* `string[] | number[]`. You could use a custom type to create a better array type though:
    type BetterArray = T extends T ? T[] : T[];
    type CrappyUnion = string | number;
    function addToCrappyUnion(arr: BetterArray) {
    arr.push(69); // Compilation error
    }

    • @raenastra
      @raenastra Рік тому +2

      This is usually not what you mean though - you'd expect an array of number | undefined to be (number | undefined)[], rather than number[] | undefined[].
      The issue is deeper than this, and comes from TS having to drop guarantees to wrangle JS into a usable type system (trying to stay typesafe while dealing with shared references, mutability, function parameter invariance + array covariance, etc)

  • @MrOnePieceRuffy
    @MrOnePieceRuffy Рік тому

    7, 8, 9, 14 and 15 is basically only 1 Point and YES, it sucks in Go to parse JSON. If the field can be string or number, you are already screwed in Go. Now you have to check the error and if the error is for this attribute which u defined default as number, but it's content was suddenly "50%" which is a string, you can only set a new struct into this place which holds a number or a string for this value.. so it's significantly easier, to just leave it as Interface and validate it on using it, which is also clearly the more dirty way to handle it.
    But I mean, what's the point now? "The JavaScript Object Notation works best in JavaScript" ... good combined, Watson

  • @jellyamna5521
    @jellyamna5521 Рік тому

    damm this is class of titan teach... , union type hit TS a lot

  • @rphyt
    @rphyt 10 місяців тому

    I get annoyed by try/catch error handling because in a lot of cases there's not enough bread crumbs to figure out where the exception is thrown... unless you print out a stack trace.... but a stack trace isn't ideal for all types of errors. I'm guilty of writing error handlers that check for return codes even in languages where exception handling is more of a standard. I like Go's choice here

  • @shariel9731
    @shariel9731 Рік тому +1

    Typescript is good for small projects. But after working on a larger scale project. HELLLL NAAHHH, never again...

  • @ikirachen
    @ikirachen 6 місяців тому

    i challange you with try/catch/finally decorator ;)

  • @janisozols5255
    @janisozols5255 5 місяців тому

    C# outclasses both of the discussed options

  • @achrefnasri8847
    @achrefnasri8847 Рік тому +1

    Ok let's just agree that he never touched go beyond "go playground" and move on cause in our line of work you have to produce Examples and evidences that convince me that Typescript is better than GO...sadly the more i read his points the more he shows his skill issues ...don't get me wrong Go has problems but it's 1 million times better handled than typescript or js ever could

  • @rickdg
    @rickdg Рік тому

    In your experience, which language has the best typing?

  • @justamuslimtotheone
    @justamuslimtotheone Рік тому

    We are not finished comparing JS to TS yet and the guy wants to compare TS to Go ! Go is the best, simply !

  • @MonkeyKong21
    @MonkeyKong21 11 місяців тому

    to be fair to javascript, parseInt() isn't trying to do the same thing as parseFloat(), and there are clear rules for how parseInt() is going to work out a mess (which it should try to do instead of failing since it's on client side)

  • @jaymason7097
    @jaymason7097 8 місяців тому

    Union types are the main thing I wish Go had.

  • @itsMurasko
    @itsMurasko Рік тому

    He definitely knows everything

  • @FrankJonen
    @FrankJonen 10 місяців тому

    How do you ship a TypeScript binary?

  • @w1-w2-w3
    @w1-w2-w3 29 днів тому

    I don't know who other guy is but he didn't have his own judgements. Every time Prime said something, his brain turn off and start agreed everything. Lack of confidence. LOL

  • @rudoka
    @rudoka Рік тому +1

    Half of these "reasons" are somebody complaining that a strongly static typed compiled language does not let you do "dynamic" things. Well, duh.

  • @vitiok78
    @vitiok78 Рік тому +1

    Go is one of the most imperative languages of them all. What the hell this person is talking about when he uses the term "functional language"? He obviously is a beginner not only in Go but in programming in general too.

  • @u007james
    @u007james Рік тому

    what about t3 channel?

  • @XEQTIONRZ
    @XEQTIONRZ Рік тому

    Never really liked try-catch / traditional exception handling since I first learned about it in college. Errors as values ftw.

    • @justsomerandomguyman
      @justsomerandomguyman Рік тому

      Go's implementation of errors-as-values is poor compared to Options/Maybes and Results/Eithers from other languages.

  • @JohnDoe-ji1zv
    @JohnDoe-ji1zv Рік тому +1

    Comparing crap like ts which was created with only one purpose to add types to js vs a modern language which was specifically designed for network stuff and perfectly fits for writing backend servers, infrastructure support etc etc. k8s is written in golang, docker is written in go and does it’s job perfectly fine. Top engineers in Google and other companies chosen Go because they know how powerful it is, and then this dude… 😂

    • @IvanKleshnin
      @IvanKleshnin Рік тому

      Unlike Go, TS authors had no luxury to start from scratch and improve everything in JS. Golang is objectively a shitty language - considering the amount of freedom and budget its creators had (and screwed: generics, error handling, sum types, etc).

    • @ahdog8
      @ahdog8 Рік тому

      I don't find "xyz is written in Go and works just fine" to be a compelling argument when compared to TypeScript. TypeScript has been used to make many things too!

  • @seasgetdegrees8268
    @seasgetdegrees8268 11 місяців тому

    I googled rule 34 when Primeagen said it (1:35)... thinking that Primeagen was referring to the cellular automaton rule 30... big rip there... (nsfw btw)

  • @scriptjungle
    @scriptjungle 11 місяців тому

    @ThePrimeTimeagen i kinda love ho many people are using go as compare to their favorite language and want to show off how theirs is "better". It kinda seems like they are all scared of go and thatfor need to proof that their favorite language is still worth using ;D

  • @InkieBeard
    @InkieBeard Рік тому

    Lol num 8. You've never needed to pull a class model from DB and then remove 6 fields from the 20 columns legacy model 🫠 `interface presentedModel extends Omit

  • @dryr-mp4pp
    @dryr-mp4pp Рік тому +179

    I've written a lot of code in both. I like the simplicity of Go, for sure. Fewer ways to shoot yourself in the foot...kind of. There are just fewer choices to make in Go, which can be a good thing.
    TypeScript is more like Scala. It can support about any paradigm you'd like to use. There are 10 ways of doing anything. You can easily over engineer a problem by adding layers of generic inheritance or something like that. Then, there's the layers of configuration. Not all TypeScript is the same. Max strict TypeScript, in practice, ends up looking much different than minimally strict TypeScript.
    The point about no union/sum types is really important. Not everyone uses these features, but once you start using patterns like tagged unions, everything starts to look like a tagged union problem. The simplest example is an Option type, which you can't make yourself in Go today.

    • @Tresla
      @Tresla Рік тому +11

      Option types are possible in Go, using Generics. They're just not as nice to work with, compared to a language like Rust which has very powerful pattern matching. Go Generics, at least in their current state, are very basic/underpowered. You could argue that that's perfect for Go, but I'd have to disagree. If you're going to add a feature like Generics, you can't half-ass it.
      type Option[T any] struct {
      Some T
      Valid bool
      }

    • @derschutz4737
      @derschutz4737 Рік тому +4

      The difference is that Scala is half decent.

    • @anon-fz2bo
      @anon-fz2bo Рік тому

      ​@@Treslahey thats a creative way to implement an optional type. but having it as a struct vs a enum just feels wrong like u mentioned. since an optional can only have 2 states, it makes more sense to abstract it as an enum, which u cant do in go unfortunately since enums in go are just untyped uints.

    • @Tresla
      @Tresla Рік тому +3

      @@anon-fz2bo I wholeheartedly agree. Go's lack of a truly generic enum type is one of its sore spots.

    • @PamellaCardoso-pp5tr
      @PamellaCardoso-pp5tr 2 місяці тому

      The whole thing about optional type is you staying inside the Maybe/Option monad and delegating the error handling to the monadic structure. No need for a enum or some shit like that, thats just a neat sprinkle on top of your chocolate milk, but the chocolate milk itself doesnt need it to be delicious.

  • @vitiok78
    @vitiok78 Рік тому +88

    The main problem of this article is that the author just wants to write Typescript code using Go. This is the stupid idea that doesn't work with any programming language.
    You just need to learn how to write idiomatic Go and most of those "problems" won't even appear in your project.

    • @elevationsickness8462
      @elevationsickness8462 Рік тому +8

      Doesnt it give you inspiration. Anyone (with the right connections) can become a journalist these days

    • @gmdias0_
      @gmdias0_ Рік тому

      makes sense

    • @anon-fz2bo
      @anon-fz2bo Рік тому +4

      for real, the nil pointer arguement is dumb, u just have to remember to check if its nil. which if u write c/c++ you should already be comfortable with.

    • @vitiok78
      @vitiok78 Рік тому +2

      @@anon-fz2bo I think he meant that in Go interface that contains nil is not nil. For example:
      var i *int // initializes to nil
      var something interface{} = i
      fmt.Println(something == nil) // prints false
      That's why it is very bad to write your own error type that implements error interface. Because it won't be nil when you return it

    • @voskresenie-
      @voskresenie- 23 дні тому

      I've worked with so many of these people when a company I used to work at adopted go. Not only were people not writing idiomatic go, they couldn't even be consistent about what language they _were_ writing via go - java, C++, python, and others. It was a nightmare for the few of us who actually had learned go properly and weren't just angry at the language over it not being a different language.

  • @bitmasked
    @bitmasked Рік тому +244

    Go's error handling is amazing because it keeps it as part of the control flow. Exceptions are the bane of new and "mature" codebases alike, especially within a 20 mile radius of any junior engineer.

    • @ThePrimeTimeagen
      @ThePrimeTimeagen  Рік тому +134

      i hate exception handling with try catch

    • @OnFireByte
      @OnFireByte Рік тому +30

      Go error handling is better than ts for sure, but most of the time i just wish they do something like rust that wrap error in Result enum, or at least have some syntactic sugar like “?” operator in, again, rust

    • @thewarsawpakt
      @thewarsawpakt Рік тому +3

      @@ThePrimeTimeagen thoughts on elixir/erlang error handling?

    • @jarvenpaajani8105
      @jarvenpaajani8105 Рік тому +2

      ​@@ThePrimeTimeagen except in zig

    • @KevinCaffrey
      @KevinCaffrey Рік тому +13

      The biggest gap in Go error handling imo is the lack of a “must use” annotation like Rust has. If a function returns only an error, it can be easy to accidentally forget to check for error.

  • @kidus_f1
    @kidus_f1 Рік тому +9

    I'm wondering how Melkey could have a Go course on Frontend Masters when he doesn't know how slices work, it's basic stuff

  • @Kane0123
    @Kane0123 Рік тому +68

    Watched a few of Melkey’s videos recently, seemed to have a fairly reasonable opinion on most things… where is he on the Theo-Prime scale?

    • @gastrader9993
      @gastrader9993 Рік тому +7

      An absolute beauty. Best of both worlds

    • @ejazahmed4609
      @ejazahmed4609 Рік тому +11

      He seems like a junior in comparison. I don't know about his qualification but that's the impression I get.

    • @antonpieper
      @antonpieper Рік тому +1

      Can you elaborate on the Theo-Prime scale?

    • @orelweinstock
      @orelweinstock Рік тому +11

      Theo gg is a startup hacker developer productivity focused get stuff out the door
      Prime is a high scale optimal code, ergonomics freak, elite coder

    • @joseandkris
      @joseandkris Рік тому

      Actaully a good comparison

  • @adambright5416
    @adambright5416 Рік тому +11

    arrays are values, slices are pointers to an array. append returns a copy of a pointer to the same array; BUT if underlying array grows because of append, it will create a new underlying array and return new pointer to new array.

  • @iojourny
    @iojourny Рік тому +10

    Holy shit, 1 hour. Lets go

    • @avi7278
      @avi7278 Рік тому

      yeah let's go. what your name?

  • @PhatPazzo
    @PhatPazzo Рік тому +4

    Come on… try/catch is the worst, but golang error handling is still not “beautiful”. Please correct me if I’m wrong, but if you ignored the error on line 49 (12:24), go doesn’t catch that without a linter, right? And about readability, there are five statements there totaling 18 lines, that kind of error handling completely throws code overview out the window. In a world where we have algebraic data types such as Result and Maybe/Option, the solution in golang is at best acceptable, but absolutely not beautiful…

    • @TheCalcaholic
      @TheCalcaholic Рік тому +2

      Like everything in go, it's not beautiful, it's not the most readable, but it's robust and functional.
      I much prefer the style of rust over go and I'm kinda undecided whether I like Java's or go's error handling better (at least, both are explicit).
      But I think we can all agree, that error handling in JS/TS is a pain in the ass.
      In go, while you can ignore an error, you know that you are doing it (because you need to use a placeholder for the error result explicitly)

  • @sinom
    @sinom Рік тому +28

    Golang's value errors would be nicer or they instead were some result return type with monadic operations on it

    • @Entropy67
      @Entropy67 Рік тому +2

      Agree but you get some interesting freedom with what it is right now 🤔

    • @Qrzychu92
      @Qrzychu92 Рік тому

      ​@@Entropy67you don't have to use the monadic things everywhere

    • @OzzyTheGiant
      @OzzyTheGiant Рік тому

      I don't want to resort to whataboutism but C has the same thing, if I recall correctly, and yet no one bats an eye

  • @svenyboyyt2304
    @svenyboyyt2304 Рік тому +8

    I think you have to differentiate to errors in your code to errors from user errors, like a fetch failing. If my code doesn't work, I want it to throw. If a fetch returns a 400 because the user forgot to input their age, I want Go style errors.

    • @Luxalpa
      @Luxalpa 10 місяців тому

      Exactly that, that's why I love Rusts error handling.

  • @nodidog
    @nodidog Рік тому +26

    As someone who actually has a couple of years experience with Go, there is NO WAY that this blogger does. They're not even aware of a lot of the basic functionality and idioms. Yikes that they felt confident enough to write an article and share it online 😂

  • @neociber24
    @neociber24 Рік тому +2

    TS is just JS, just fancier.
    The real question, what is the best type system? TS, Go, Rust, Haskell, Kotlin, ...?

  • @ameer6168
    @ameer6168 Рік тому +3

    we have to write 2x more code to make typescript type safe

  • @LusidDreaming
    @LusidDreaming Рік тому +21

    This whole article is basically saying "I don't know how to program if I don't have the full set of TS features."

    • @ivanjermakov
      @ivanjermakov Рік тому +7

      This whole article is basically saying "I like dynamically typed languages"

    • @UxerUospr
      @UxerUospr Рік тому +3

      Not just TS, but the JS frameworks and sundry other packages he must use. Apples != Oranges

    • @teejaded
      @teejaded Рік тому

      For me, less language features means when I have to read your shitty code (don't be mad, all code is shitty) I don't have to spend as long figuring out what the fuck you were doing.

  • @adamsribz
    @adamsribz 11 місяців тому +1

    Bro the CaPiTaLIZAtion thing is great. I hate having to write public on every single var to to export it

  • @911Archie
    @911Archie 6 місяців тому +1

    Actually in go this is how you say you implement an interface:
    var _ Interface = (*MyStruct)(nil)
    and then it's checked at compile time

  • @TremereTT
    @TremereTT 9 місяців тому +1

    I only like Try Catch Finally how it was inplemented in Java. And I hate java! Yet that was a thing they did right. The otherthing java did right is to put a monitor in every object, for easy threadsafety.

  • @tekhiun
    @tekhiun Рік тому +1

    If you gonna use ParseInt and Number as example of bad behavior of JS you might as well scream that you don't read documentation instead.
    It's on the same level as people that complain that JS follows floating point standards thinking it's odd behavior on JS side. There are a lot of issues with JS ,like Prime showed with Json parse, but saying that the code doesn't follow your intuition is not one of them.

  • @kubre
    @kubre Рік тому +3

    32 best reasons to develop depression

  • @yapet
    @yapet Рік тому +4

    About your "zod competitor" idea. Instead of doing a build step which will codegen validators, you can use the "new Function()" pattern to generate code in runtime.
    It’s the same approach that fastify uses to generate fast json serializers / deserializers given json schema definitions.

    • @majorhumbert676
      @majorhumbert676 Рік тому

      This idea was already implemented. Look up "Typia"