No BS TS #4 - Function Overloading in Typescript

Поделиться
HTML-код
  • Опубликовано: 18 сен 2024

Комментарии • 118

  • @devsbookclub
    @devsbookclub 3 года назад +33

    you're an amazing educator Jack! i love how you explain the concepts in depth but also bring up the simple things like what is unknown, when it become contextually necessary.
    SOO much better than some other tutorials just blurting out every thing with no context because the way you teach things actually sticks!!!

    • @jherr
      @jherr  3 года назад +10

      Thank you so much for that. I really appreciate it. I genuinely do try to structure stuff in a way where it's relevant and accessible, and hopefully sticky like that.

  • @slikk66
    @slikk66 3 года назад +17

    this series is gold, great content

  • @ronniecorbett
    @ronniecorbett 3 года назад +38

    Great channel Jack!
    You could use keyof to avoid a hardcoded type -> coord[key as keyof Coordinate] = parseInt(value, 10);

    • @jherr
      @jherr  3 года назад +8

      Nice! We actually will be covering `keyof`, but for some reason I didn't think of using it here. Nice catch!

    • @anshikgupta2993
      @anshikgupta2993 2 года назад

      key as 'x' | 'y' really confused me. Can you explain how it resolved the issue?

  • @william3588
    @william3588 3 года назад +6

    Pure awesomeness

  • @lifeok6188
    @lifeok6188 3 года назад +5

    Nice setup with perfect light 👍. Jack is becoming younger day by day 💪 😎

  • @alanshortis958
    @alanshortis958 2 года назад +7

    A small change I made after some googling: instead of repeating the valid keys as `coord[key as 'x' | 'y']` you can define a new type for valid keys in the Coordinate interface: `type CoordKeys = keyof Coordinate`, then use it as `coord[key as CoordKeys]`.

  • @MrWickedsouls
    @MrWickedsouls 2 года назад +2

    "Feel free to share with your friends" Coders don't have friends, and if they do, they wont understand Overloading. Great video!

  • @floofthefops
    @floofthefops Год назад +1

    This has to be the best and easiest to understand series. It also goes deeper into actually implementing useful stuff. Thank you

  • @geneartista9714
    @geneartista9714 2 года назад +2

    Thanks for taking up your expensive time to create us these good tutorials.

  • @abdellahcodes
    @abdellahcodes 3 года назад +3

    Jack posts. I watch. That simple.

  • @8koi245
    @8koi245 Год назад +1

    Loving it, I went a little beyond and figured out that if we get arg2 it'd be number so I did that and indeed worked just fine!

  • @3DPTR
    @3DPTR 2 года назад +2

    I love these videos , I try to watch one every day because those are sensible concepts about TS , I would like to know them by heart ! thanks Jack!

  • @Moonwalkerrabhi
    @Moonwalkerrabhi 3 года назад +1

    These videos should have like 50x more likes and comments than they are , this is pure gold content

    • @jherr
      @jherr  3 года назад

      Thank you!

  • @juhandvan
    @juhandvan 2 года назад +1

    The example is very simple to get it. Thank you so much, Jack

  • @Fullflexno
    @Fullflexno 3 года назад +2

    Thank you for providing so much good information. Cheers from Norway. I love your teaching style! «cool»
    Again thank you!

  • @mandihaase2744
    @mandihaase2744 2 года назад +1

    These videos are incredibly helpful! Thank you so much for all the work you do to help the developer community~

  • @yosha2467
    @yosha2467 3 года назад +8

    Just a slight error fix for 5:35 there is no such thing as type casting in TypeScript, 'as' is type assertion which basically says "I declare that this is whatever I say it is" making the compiler raise its hands and just assume that what you wrote after 'as' is true.

    • @jherr
      @jherr  3 года назад +2

      You are correct, it's not a runtime coercion.

  • @ram-bk4mu
    @ram-bk4mu 2 года назад +1

    This is great! I have watched many videos of TS but nothing like this!! thanks a lot!

  • @mananbari4725
    @mananbari4725 Год назад

    I love how you teach such advance and complex data manipulation and structing a really nice code
    Love From Pakistan♥❤❤

  • @darkmift
    @darkmift 2 года назад +2

    As overloading is not native to js this was interesting to learn as a concept.
    I feel however this may be something to be avoided in practice due to the potential confusion a function with several implementation may lead to.

    • @jherr
      @jherr  2 года назад +1

      IMHO, overloading is mostly about legacy library support.

    • @nickwoodward819
      @nickwoodward819 2 года назад

      If all the declarations are next to each other would it really be confusing? Surely it's like saying overloads would cause confusion in Java? Developers know they exist in TS, just as they would in Java.
      Just my 2 cents, but everytime I hear this as a reason not to use them I hear "this isn't javascript". Which is surely the point! :)

  • @sonalkumar702
    @sonalkumar702 2 года назад +1

    No BS you are very good at explaining thing.

  • @fares.abuali
    @fares.abuali Год назад +2

    Thank you so much!
    This is very useful

  • @fernard8985
    @fernard8985 2 года назад +1

    Hi Jack, in the last example, i think coord[key as keyof Coordinate] looks pretty neat too.

    • @pooyaestakhry
      @pooyaestakhry 2 года назад

      I guess it was better to check whether it's (x | y) or not by an if block, cause there might be an error while sending those coordinates. Also i would trim the strings.

  • @137dylan
    @137dylan 2 года назад +1

    Hi Jack,
    2 incredibly important points I would like you to clarify, please:
    1. Did you record this series on the same day and purposely change your shirt for each video? If so, that makes them even better!
    2. It's obvious you're American, but I can't pinpoint your accent. I have a feeling you traveled around a lot when younger so never formed a specific US regional accent..
    Thanks!

    • @jherr
      @jherr  2 года назад +1

      #1 Probably. If I have the content ready to go I like to do 2-3 and then edit and all that in one go.
      #2 I'm from Philly (Philadelphia) originally. There are a lot of Philly-isms in how I talk, or really slur, particular sounds. I'm working hard on trying to get rid of those, but old habits are hard to break.

  • @josemfcheo
    @josemfcheo 3 года назад +1

    Awesome videos, I'll gonna start to share this channel with my friends

    • @jherr
      @jherr  3 года назад

      Fantastic! Thank you!

  • @jeremythompson8697
    @jeremythompson8697 8 месяцев назад +1

    Hi Jack, this is great - especially for multi-lingual programmers. I've got a question, this overload function parseCoordinate(obj: Coordinate): Coordinate; - you declare the "let coord = 0 ,0" and you return that, however when I call the parseCoordinate with a Coordinate it simple returns what I passed in by ref. And in the overload implementation there is no way to access the obj argument, "Cannot find name 'obj'". So how does it magically assign coord = obj; ? Thanks appreciate your time and effort!

  • @mark-at-driva
    @mark-at-driva Год назад +1

    Great content and great shirt

  • @josemfcheo
    @josemfcheo 3 года назад +2

    This is art

  • @NuncNuncNuncNunc
    @NuncNuncNuncNunc Месяц назад

    Found this late, but type coercion using 'as' is almost always a warning that something is not right. Type guards that introspect the arguments and tell the compiler that the value is safe to use as the desired type offer much more protection.
    For example, in the example code passing any object to parseCoordinate, such as { name: 'typesafe' } will return that object to callers and be treated as if it had x and y number fields resulting in a runtime error in this case.
    Another example, let a = parseCoordinate({ x: '1', y: '2' }). If you have a sum coordinates method taking two Coodinates and pass it a for both you will get an object, { x: '11', y: '22' } that the compiler still thinks is a valid Coordinate.

  • @BHFJohnny
    @BHFJohnny Год назад +1

    I think even this simple example can get very complex very quickly if I want to be really safe :D.
    1) Check if the object actually has the fields I need
    2) Check if x and y are indeed numbers
    3) Check if the string is provided in that very specific format, something like type CoordsStr = `x:${number},y:${number}`. But then I might consider a different format, for example different chars, optional space after comma etc. So I'd make a different overload functions and implement super complicated logic for checking the format (probably regex)
    Edit: No, just realized first two points are already ensured. So I'd do that maybe only to support Javascript use without getting some wierd values as a result. Like x being a function callback and y being all seven books of Harry potter

    • @jherr
      @jherr  Год назад +3

      Function overloading exists to solve the problem of interop with legacy JS APIs that had complex function parameter patterns, like $ in jQuery. I generally speaking wouldn't start a function native to TS using function overloading unless I had a really good reason to. Not just because it's probably a weird API signature, but also because I'm doing a lot of work at runtime on every call to figure out which signature I'm getting called with. Just IMHO.

    • @NickKoster
      @NickKoster Год назад

      ​@@jherrI'm confused now :) In the video you say overloading is one of your fav features but here it reads like you don't use overloading unless you had a good reason to? Or I am just misunderstanding something...

  • @lorenzodallamuta138
    @lorenzodallamuta138 2 года назад +2

    Extending the idea that type checking doesn't extend to runtime, if you provide an input like "a:57,b:38" the overload for parsing strings will mistakenly return something along the lines of { x: 0, y: 0, a: 57, b: 38 } and typescript won't be able to warn you because it can't see into the result of parsing the string before it happens. So I'm not sure this is a good example, but maybe you point this out already in your interview questions... :P

    • @jherr
      @jherr  2 года назад

      Fair enough, but it's not unusual, you might have to make that type of string parsing code for reading data from a file, and yeah, the implicit contract there is that your code will ensure the type-safety it advertises.

    • @iukys3889
      @iukys3889 Год назад

      This is definitely not type safe, using as all over the place like this :p worth to mention …

  • @jdratlif
    @jdratlif Год назад

    Love your content. I would've parsed the string with regex rather than the multiple splits.

  • @PS-dp8yg
    @PS-dp8yg 3 года назад +2

    Awesome content! I'm not a typescript developer and never knew typescript supported function overloading and learned something new today. However, with that being said, I'm not a fan of this at all! The way typescript handles function overloading is just gross. Can you imagine the checks needed if wanting to support more scenarios?

    • @jherr
      @jherr  3 года назад +3

      Undoubtedly a lot, but this is what some JS functions were doing anyway. This is just a way to put different type signatures on it, so that it's easier for someone to consume a function that is written this way.
      You don't have to use this mechanism and you don't have to write a single function that takes a variety of arguments. But if you do, this feature will help you express the API surface of that function far more succinctly.
      I understand where you are coming from. In other languages each implementation would have its own body. But Typescript is limited (by design) in that it the type annotations can be removed from the code and the code should still run. So since JS can't support function overloading the "usual way" it's not possible for Typescript to support that either.

    • @PS-dp8yg
      @PS-dp8yg 3 года назад +1

      Thanks for the reply. I have a hard time why typescript cannot support each function to have its own implementation. I understand why in JS we can't because of the dynamic nature of the language and the ability to pass N number of arguments.

    • @jherr
      @jherr  3 года назад +4

      @@PS-dp8yg Two reasons, first that Typescript isn't adding new language features to JS and is designed to be removable. And second that the code generated by TS has to be JS, and compatible with JS. So in order for that to work the compiler would have to merge your implementations into one function and then write the detection code to route you into the right version.

    • @PS-dp8yg
      @PS-dp8yg 3 года назад +1

      @@jherr I see. Thanks and subbed.

  • @okerror1451
    @okerror1451 3 года назад +1

    Whoa, I had totally missed that overloading was possible in Typescript.

    • @jherr
      @jherr  3 года назад

      Possible-ish. It's not the same as a C++ or Java.

  • @bobvantpadje1490
    @bobvantpadje1490 3 года назад +2

    Why would you personally prefer this over creating three separate functions? I feel like the readability and maintainability for code that uses function overloading is much higher than just creating three separate functions. Even if you want to have to parse functions close to each other you could just put them in an object, so you can call it like this: parseCoordinate.fromStrin(arg) or parseCoordinate.fromNumbers(arg1, arg2).
    For me this gives me a much better sense of what is going on inside my function. What would be your reasons to prefer function overloading over just creating multiple functions?

    • @bobvantpadje1490
      @bobvantpadje1490 3 года назад +2

      Love your content btw :)

    • @jherr
      @jherr  3 года назад +4

      I tend to look at the value of a function as proportional to it's reuse. A good function gets reused a lot. So I'm ok with trading a little implementation complexity for making a function that hints it's use really well, which is what function overloading allows for.
      Also, I usually go for lower numbers of exported functions if I can. So if I were making an XML parsing library I'd ideally like to have one function, parse, that would take a string, a stream handle, etc.and just do the "right thing" (tm). :) And function overloading would allow me to express all the variations of "parse" in that context.

  • @yt-1161
    @yt-1161 Год назад +1

    @8:00 why do you need extra ’as string' there if arg1 === 'string' ?

  • @channabandara
    @channabandara 2 месяца назад +1

    valuable

  • @sreekar_s
    @sreekar_s 3 года назад +3

    Is it also okay to use unions eg. arg1: Coordinate | number

    • @jherr
      @jherr  3 года назад +1

      Yep.

  • @thehaptiK
    @thehaptiK 2 года назад +1

    Perfection;

  • @oOrbitZz
    @oOrbitZz 2 года назад

    very cool stuff. I love this channel. I also tried below as the default to shorten the code. And remove the else part.
    let coord: Coordinate = {
    x: arg2 as number,
    y: arg2 as number,
    }

  • @zykoz6826
    @zykoz6826 2 года назад +1

  • @nickwoodward819
    @nickwoodward819 2 года назад

    Hi Jack. Great video again, thanks!
    Quick question if you don't mind. I had thought 'as Type' and '' would be interchangable - and they seem to be, until @8.05, when you type `(arg1 as string).split()`.
    `arg1.split()` doesn't work in its place, but assigning it to another variable `const arg = arg1; ` then calling `arg.split()`, does work, and I was just wondering why?
    Thanks!

  • @sagarreddy7461
    @sagarreddy7461 3 года назад +1

    Great content jack

  • @vzlomer1000
    @vzlomer1000 2 года назад +1

    thanks, good video

  • @SahilRajput03
    @SahilRajput03 Год назад +1

    awesome, superawesome! Amazing

  • @unfocuseddev4921
    @unfocuseddev4921 Год назад +1

    What's the point of declaring the parseCoordinate function three times before the actual implementation? If I remove those declarations, the code runs anyway, since the final parseCoordinate function accounts for all three argument types.

    • @jherr
      @jherr  Год назад

      The code will run yes, but that's always the case with TypeScript. The function overloading is only helpful to TypeScript to provide more restrictive (and accurate) function signature combinations.

    • @unfocuseddev4921
      @unfocuseddev4921 Год назад

      @@jherr Got it, thanks! Also, 30 minute response time to a comment on a 1.5 year video - wow. You're doing an amazing job.

  • @Calebwaldner
    @Calebwaldner 3 года назад +1

    Great video

  • @AntonShestakov
    @AntonShestakov 3 года назад +1

    Thanks

  • @alexandre158
    @alexandre158 3 года назад +1

    Why not returning directly from inside the ifs conditions ?

    • @jherr
      @jherr  3 года назад

      Personal style. You could return out of the if's if you wanted to.

  • @avneet12284
    @avneet12284 3 года назад +1

    Wow !

  • @razorbelle
    @razorbelle 3 года назад +1

    Is it possible to do function overloading for arrow functions in TypeScript?

    • @jherr
      @jherr  3 года назад +1

      Not in the same way because you are defining a constant value and not a function. You can define a pretty complex function signature that takes multiple variants and returns multiple different types based on conditionals. But you wouldn't get the same quality of hinting that you do with the function approach. The overloaded function approach gives the consumer a list of the possible approved variations of function signatures.

  • @gideon763
    @gideon763 Год назад +1

    I find it very useful, but why would I want to overload functions like this? Wouldn't it be better to define dedicated functions for each kind of parameter? Such as "getCoordinatesFromString", "getCoordinatesFromNumbers", etc...?

    • @jherr
      @jherr  Год назад +1

      Javascript allows for making functions that take different types of arguments. Function overloading just makes that compatible with TypeScript. A classic example of this is the jQuery $ function. It would be a shame if we couldn't write jQuery code using TypeScript. TypeScript is designed to support all of the potential features of the JavaScript language, even those you don't choose to use.

  • @lookingforbino
    @lookingforbino 2 года назад +1

    Hi Jack,
    I just searched, JavaScript doesn't support function overloading, so ....
    function parseCoordinate(str: string): Coordinate;
    function parseCoordinate(obj: Coordinate): Coordinate;
    function parseCoordinate(x: number, y: number): Coordinate;
    ------- divider----------
    from my understanding, the previous functions will be overwritten. How do you make them work?
    Thanks

    • @jherr
      @jherr  2 года назад +1

      You are correct that JS doesn't support function overloading. The last function along the line needs to implement all of the previous API signatures. This feature is primarily around giving a function that has multiple argument signatures and easier to understand type signature in TypeScript.

    • @lookingforbino
      @lookingforbino 2 года назад

      @@jherr Meaning, only "function parseCoordinate(arg1: unknown, arg2?: unknown): Coordinate { } " works here. The previous 3 functions stay there just for the demonstration, they don't work, right ?

    • @jherr
      @jherr  2 года назад +2

      @@lookingforbino They don't work, but they aren't there for the demonstration. TypeScript will check to ensure that your call pattern of parseCoordinate matches one of the function overload patterns.

    • @lookingforbino
      @lookingforbino 2 года назад

      @@jherr Thanks Jack

  • @srkuleo
    @srkuleo Год назад

    I just have one question.
    Why are you casting arg1 as string (line 16) since for this block to even run arg1 must be string, so if condition passed you would know for sure that arg1 would be a string? I don't see the point of casting it as one... Thanks.

  • @rachkulk3209
    @rachkulk3209 9 месяцев назад

    Great tutorial. Thanks for the series. Why typeScript is not yelling for below code? [vals[0]] below can be anything other than x,y also.
    if (typeof arg1 === 'string') {
    arg1.split(',').map((val: string) => {
    const vals = val.split(':');
    coordinate = {
    ...coordinate,
    [vals[0]]: Number(vals[1]),
    };
    });
    return coordinate;

  • @emdadgar_official
    @emdadgar_official 2 года назад +1

    i hope see many more course about TS from you . everything is clear upuntill although you don't speak very clear English for non-eng x)

    • @thingshappen5607
      @thingshappen5607 2 года назад

      This is funny :) This guy is American. Thanks for putting an effort into this series, Jack! 🤘

  • @thatboyneedstherapy
    @thatboyneedstherapy 3 года назад +1

    Would I be right in saying it's not possible to make two overloads that each receive a type (say, one receives a Coordinate and the other receives a Tile), because those would both get compiled down to 'object' in JS?

    • @jherr
      @jherr  3 года назад +1

      Give it a try. It should work because the important thing is the compile time constraints that you are putting on the function. You are right, at the end of the day, it's all an object. So the implementation function is going to have to figure out which one is which.

    • @dorinpopa6962
      @dorinpopa6962 2 года назад +1

      It works and you can even make the implementation more elegant on the typing side by using type guards instead of some combination of typeof and some other means of differentiating between different object types.

  • @anonymoussloth6687
    @anonymoussloth6687 Год назад

    Object keys are treated as strings? When you did key as 'x' | 'y' does that mean the keys are kept as strings?
    In a previous video, u made an object IDs which had key-value pairs like this: 10:'a'.
    In this, the key 10 is also kept as a string?

    • @jherr
      @jherr  Год назад +1

      Object keys can be strings, numbers or symbols.

    • @anonymoussloth6687
      @anonymoussloth6687 Год назад

      @@jherr but x is a symbol right? Why did you cast it as string then?

    • @jherr
      @jherr  Год назад

      @@anonymoussloth6687 Can I get a time reference so that I can help you out better.

    • @anonymoussloth6687
      @anonymoussloth6687 Год назад

      @@jherr 9:19 it's when you did key as 'x' | 'y'
      X and y are symbols right? Shouldn't it be something like key as x (without the quotes)?

    • @jherr
      @jherr  Год назад +1

      @@anonymoussloth6687 No, 'x' and 'y' in this case are "string literals" www.typescriptlang.org/docs/handbook/literal-types.html#string-literal-types . They are not JavaScript symbols.

  • @cihadp
    @cihadp Год назад

    Maybe it is better if last overloading function's string parameter is like type StringCoordinate = `x=${number},y=${number}` | `y=${number},x=${number}`

  • @韦磊-o4b
    @韦磊-o4b 2 года назад

    why not use specific type instead of unkown? like:
    function parseCoordinate(p1: Coordinate|string|number, p2?: number): Coordinate {// some code}

  • @brahim_boussadjra
    @brahim_boussadjra 3 года назад +1

    I've tried out to overload a function and it doesn't work

    • @jherr
      @jherr  3 года назад +1

      Jump on the Discord server and into the #typescript channel and tell us what your issue is and maybe we can help you out.

  • @xanderexpelimus5237
    @xanderexpelimus5237 2 года назад

    type DescribableFunction = {
    description: string;
    (someArg: number): boolean;
    };
    function doSomething(fn: DescribableFunction) {
    console.log(fn.description + " returned " + fn(6));
    }
    how do we run this? i don't get it

    • @jherr
      @jherr  2 года назад

      Like this:
      const descFunc = (x: number) => x > 5;
      descFunc.description = "describable function";
      doSomething(descFunc);

  • @KhanhNguyen-hd7ws
    @KhanhNguyen-hd7ws 7 дней назад

    What if there’s 2 different objects types?

  • @rokinos
    @rokinos 2 года назад

    parseInt(value, 10) = Number(value) = +value

    • @jherr
      @jherr  2 года назад +1

      Truth. Old habits die hard.

    • @rokinos
      @rokinos 2 года назад

      @@jherr I couldnt understand parseInt(value, 10), it wasn't clear as Number(value) or +value

  • @MaksymMinenko
    @MaksymMinenko 2 года назад

    Instead of "ts-node" I use "tsc --watch" in one terminal, and "nodemon build/...js" in the other.

    • @jherr
      @jherr  2 года назад

      Have you looked at tsx?

    • @ChillAutos
      @ChillAutos 2 года назад

      What do you mean about tsx? I do exactly what the max said daily. What's the issue with it? Also love your content.

    • @jherr
      @jherr  2 года назад

      @@ChillAutos Can you give me a time reference?

    • @ChillAutos
      @ChillAutos 2 года назад

      @@jherr Sorry what I meant was I didnt understand your reply to the top comment in this thread "Have you looked at tsx?". What was the issue with that?

    • @jherr
      @jherr  2 года назад

      @@ChillAutos Ahhh, gotcha. My bad too. Anyway, tsx is a new alternative to ts-node: www.npmjs.com/package/tsx Totally confusing name though for sure.

  • @dannyroberts4067
    @dannyroberts4067 2 года назад

    I like these videos but there is a tendency to explain the obvious stuff but gloss over the complicated stuff

  • @Dylan_thebrand_slayer_Mulveiny
    @Dylan_thebrand_slayer_Mulveiny 2 года назад

    Anyone who thinks this generates better code is delusional.

    • @squdge
      @squdge 2 года назад +1

      Never have I felt a more secure react application than when I switch to Typescript. So I guess, that's just like your opinion dude.

  • @Smithy-so9be
    @Smithy-so9be 3 года назад +2

    Another great video. You can also combine this with user defined type guards to cut down on casting values: basarat.gitbook.io/typescript/type-system/typeguard#user-defined-type-guards