JavaScript Air

038

Wed, Aug 31, 2016

August

12:00 pm CT

Adding typings to JavaScript is becoming more and more popular. We're going to chat with the creators of TypeScript and Flow to discuss the why and how behind typed JavaScript.


Audio


Video



Links, Tips, and Picks

Anders Hejlsberg Profile Picture

Anders Hejlsberg

Tips
  • Follow your passion. Go Play. Write some new code. That’s how you do your best work. Try to enjoy what you’re doing.
  • There are lots of people coming to JS now. Lots of OOP programmings flowing into the ecosystem. JS can be a great FP language though. There’s a lot you can learn from studying FP in JS.

Jeff Morrison Profile Picture

Jeff Morrison

Links
Tips
  • Have a "just get it working" mentality. Then clean it up after

Brian Lonsdorf Profile Picture

Brian Lonsdorf

Tips
  • Functions should be input to output. Type systems help a lot more when you compose this way.
  • Stay away from Object|Any :)

Kent C. Dodds Profile Picture

Kent C. Dodds

Tips
  • No matter how well you know something, keep your mind open to learn even more about it.


Transcript

KENT: And we're live with JavaScript Air. Hello, everyone! My name is Kent C. Dodds, and I am your host for this JavaScript broadcast podcast that we love so much, it's called JavaScript Air. This is episode 038. And today, we're gonna be talking about typed JavaScript with TypeScript and Flow, two of the most popular type checkers in the JavaScript world. I'm really excited about it because we have the original creators of these projects on the show today. And I'll introduce them to you in a brief moment but yeah, today's show is gonna be awesome.

I definitely want to give a shoutout to our sponsors that enable transcripting and the newsletter, so Egghead.io is the show's premiere sponsor. And they have a huge library bite site with development training videos, check them out for content on JavaScript, Angular, React Node and more. Egghead.io is also the host of two free Redux courses from Dan Abramov. Find them at Egghead.io/Redux. And Front End Masters is a recorded expert-led workshop with courses on Advanced JavaScript, Asynchronous and Functional JavaScript, as well as lots of other great courses on Front End topics. Check them out at frontendmasters.com.

And TrackJS, reports bugs in your JavaScript before customers notice them. And with their telemetry timeline, you'll have the context to actually fix them. Check them out and start tracking JavaScript errors today at TrackJS.com.

And actually I just wanna give a quick shoutout to all three of those sponsors. All three of them have been with the show since the very beginning, almost a year ago, like nine months ago. And so I'm just super, super grateful for their support, they've been awesome. So, thank you Egghead, Front End Masters and TrackJS.

And then WebStorm is a powerful JavaScript IDE. Working with Angular, React or Node? Then you don't want to miss it's super intelligent coding assistance. Use the discount code JAVASCRIPTAIR at checkout at jetbrains.com/webstorm to get 20% off your WebStorm personal subscription.

And finally, Trading Technologies is looking for passionate and inventive full stack JavaScript developers, who want to work on cutting edge solutions in a collaborative and challenging environment. Go help them build the top choice platform for derivative traders.

Alright sweet, so, also a fun thing about this recent change with Hangouts. I actually, I totally forgot to mention, a couple, like two weeks ago I said, "Hey, like this show might end because Hangouts On Air is being cancelled," and like sadness and tears everywhere. Turns out that actually Hangouts on Air is just being moved from Google+ to YouTube Live, and so like, all the normal functionality, everything is exactly the same. In fact we're using YouTube Live for this show. So, one actually kind of cool thing about this is because it's on YouTube, there is now a chat and several of you watching live right now are enjoying that chat feature right now. There is a code of conduct. And if we have trouble in the chat then you will be blocked, so please adhere to the code of conduct. You can find it at jsair.io/coc, or just like find code of conduct on JavaScript Air's GitHub, that's where that goes too. But yeah, please adhere to that and we will all have a fun time. Hopefully we can keep the chat going.

But I am still going to use Twitter for the live questions, for those of you watching live just because that's a little bit easier for me to manage, I've got a workflow for that already so that I don't miss out on questions. So if you do have a question for the guests, that we'll ask at the end of the show, then use Twitter, with the hashtag #jsAirQuestion. And also, this is a weekly show that we just totally love and so make sure that you tune in next week, same time, same place, the normal time, for our show on NodeJS and community. It's gonna be a great show, and I hope that you enjoy it. And then as always, follow us on Facebook, Twitter, and Google+ to keep up with the latest. Although Google+ is not my favorite thing anymore because they totally killed Hangouts and that makes me sad, so. (laughs) I'm just joking, alright, sweet. So let's introduce people. First for our panel we have Brian Lonsdorf.

BRIAN: Hey, how's it going?

KENT: And again, my name is Kent C. Dodds. For our guest today, super excited, we have Anders Hejlsberg.

ANDERS: Hey guys.

KENT: And Jeff Morrison.

JEFF: Hey, how's it going?

KENT: Thank you both for coming. So let's go ahead and just get an intro to the people that we're chatting with today. Anders do you want to go first?

ANDERS: Sure. So I'm Anders Hejlsberg, I'm a technical fellow in the (mumbles) Enterprise Group at Microsoft and I work on development tools. And I've been working on development tools for probably, 30-35 years. I've worked on Turbo Pascal was my first product and then I worked on Delphi. And then I came to Microsoft and I was the architect of C#. And I still dabble in that and then I've been working on the TypeScript project for the last five years or so.

KENT: Cool, cool. Thank you so much for all your work. Yeah, literally, tens, hundreds of thousands of developers are grateful. (laughs) So awesome, and Jeff.

JEFF: Hi, I'm Jeff. I work on the product infrastructure group at Facebook. We do sort of infrastructure related to development tools as well as product development of Facebook. specifically for the past several years at Facebook I've been working on JavaScript tooling, so anything from our compilation infrastructure to, I now work on Flow full time. I also sit on TC39 as well, and work with real closely with TC39. Yeah, that's me.

KENT: Thank you so much for joining us today. So, like I said before we started the show, this should hopefully be like the hallway track of a conference and we're going to chat about types in JavaScript. So you're kind of subject matter experts. I think like, I always like to start with a good baseline so everybody knows what we're talking about, and that we're all like talking about the same thing. And so, let's first talk about what are types. And I kind of want to go deep, like, you know, did types exist when we were still doing punchcards in the computer and stuff? Like when did types become relevant and why do we have them? So anybody feel comfortable taking that on?

ANDERS: I can say something at least and then maybe Jeff could jump in. Well I mean, types have always been around. And types are even around in JavaScript, it's just they're not manifest in the program that you're writing. But at run time, things have types, right? I mean, you have numbers and you have strings and you have Booleans and objects and so forth. But one of the things that distinguishes statically-typed languages from dynamically-typed languages is whether or not you have the ability to reason about the types before you run your program and whether you have tools to do that reasoning. And that's really what, you know, JavaScript doesn't have. You find the errors and other than syntax errors, you know, that are reported by your JavaScript VM, you don't find the errors until you run the program and nothing attempts to reasons about the validity of the program before you hit the problem (laughs) so to speak. And of course, we know from statically-typed languages that it's much better to find the bug before the space shuttle flies than whilst it's flying right? I mean so, if you can do that then, you know, you can be presumably more productive.

JEFF: Yeah, I would add also you know, that's a great sort of sort of summary of types. You also have this utility of types, especially the history of types where they actually go into making a program run, historically, right?

ANDERS: Mh-hm.

JEFF: So, before you know until recently, relatively recently at least, we had these higher level languages now that can sort of do these dynamic runtime checks and doesn't actually, you can still have a performing language that way. But originally, you know you had to compile these languages down. That's where static types typically come from is at the low level, you need to understand what these types are so you can run the program. So yeah, some aspects of the types, origins of the types there kind of come from that just like raw need for running the program and (mumbles) programming languages.

ANDERS: Yeah, I'd add also that, now that I think about it more types are great for checking programs but they're also great for aiding you in constructing and maintaining programs. For example, if you think about refactoring, which is something that Java and C# and C++ has had for, you know, as tool features for a long time, you come to realize that unless you have types to guide your refactorings, they can become very dangerous. Like, if you're say renaming some identifier or property called name, there might be many different objects that all have a property called name but the one you want to rename is the property of this type or of this family of objects. And in order to reason about that, you need to know statically about how all these types relate. And that's why, you know types can help you do things that otherwise might, you know, in a 20 or 100,000-line program you could spend an entire day changing the name of one identifier and you still don't know if you got it right.

KENT: Yeah you have to kind of augment that with unit tests. And even then, you're still not 100% sure--

ANDERS: Yeah, even in unit tests you don't know, I mean, they don't tell you which parts you didn't test, right? (laughs)

KENT: Yeah, exactly. I think we had a couple weeks ago we had a show about typed functional programming in JavaScript, so this is kind of related. People watching now probably would be interested in that as well. But I believe in that show someone mentioned that like types appear to get in the way, when you're like, as you're writing the code but they totally make all of that worth it when you go to refactor or maintain the code.

JEFF: Yeah, this is an interesting sort of debate you run into, I definitely sort of, I sort of noticed there are two categories of discussion that goes on over the years while still working in this area of JavaScript. You have this sort of category of programmers who are coming from these statically type languages, Java, C++ and so on. And they're coming to JavaScript and they love their type system because when they get to JavaScript, they sort of make all these errors that you basically couldn't make before and they miss that sort of safety.

But then you have this other category of developers that are coming from JavaScript completely untyped and when, some of those developers when they hear type system they think Java, they think Java and C++. And they think, "Oh, that's just gonna get in my way. Sometimes I, you know I wanna change something over here, and it's gonna break some stuff over here but it's because I wanna see how this works, you know, I just wanna like see how this works before I commit to fixing everything down stream first." And you know, in a strongly typed language that's not very easy, typically you have to like go change all your downstream just to see if the local change even worked.

So one thing that's really cool about sort of the direction that typed JavaScript is going with both Flow and TypeScript is that you have the ability to kind of go in and you have this type checker that can inform you when you've made these breaking changes. But you can also still make those breaking changes and expect the code to run, you know, compiling isn't a precursor to running. So that's pretty cool.

BRIAN: So I had just a basic question on the use, well, maybe before we go into that, maybe we could just talk about the differences between TypeScript and Flow just to give people an idea of where they should, you know, what problems each respectively solves. Go for Flow first?

JEFF: Sure. So Flow, basically Flow sort of tackles the problem at a different architect (mumbles) than TypeScript I think. So Flow is more, is basically, it's not a compiler, it's a static analyzer. And it's purpose really is to sort of read and understand code at a deep level and just give feedback based on the code and understanding what it's pulled out. So in the process of doing that, we can actually trace data flow through the entire program as a series of constraints. So for the most part, it really is kind of a difference in like tool set and general philosophy. So when the question pops up, like, "which should I use, TypeScript or Flow?" Usually, it's which philosophy sort of aligns more with what you're going for. I don't know if that helps.

BRIAN: Certainly and yeah, I'm curious about the TypeScript side just knowing that it's a super set and what that can do for you.

ANDERS: Well, I mean well they're both super sets in that sense. I mean we have had, yeah there are different philosophies, I would say that, you know, one of the things that guided us with TypeScript was that we knew even from day one that this was about tooling. This was not about creating specifically not about creating a new language that's different from JavaScript, this was about augmenting JavaScript and helping bring to JavaScript the pieces that are missing. I think we also knew up front that this had to be an open source community and an open source project. And we knew up front that we wanted to bootstrap and self-host. And we have built TypeScript in TypeScript. And then we have also built a tool or an IDE called Visual Studio Code, all in TypeScript. And these tools all run anywhere that JavaScript runs, including in your browser. You can host a TypeScript compiler anywhere that you want. And we see people doing that, you know hosting it in webpages and teaching aids in products like SharePoint or Office, or you know? So, this was very much about not just, you know, building a type checker for JavaScript but about building value for the community at large.

I think there are some, yeah, there are some differences between how Flow type checks and how TypeScript type checks. I'm sure we'll get into that, you know, we have different viewpoints on, you know, how-- the thing that's funny about types and about type inference and advanced types systems is that in a sense, you know, the world's most intelligent type checker will simply infer a set of types for your program that make it correct. (laughs) And not tell you any errors, right? So, so this notion that you can type check something without having any annotations anywhere is, you know, at some point you gotta say something about or put down some fence posts about, you know, "No, this thing I'm gonna here assert has the following type and now please check that that is true elsewhere in the program." And so, sometimes there's debate about non-local type inference, should we infer from call sites you know what the type of a parameter is for example and there's a bunch of debate in the functional communities about whether that's good or bad, we have one view point and Flow has a different one, you know. But, there are pros and cons to both.

BRIAN: Right, just really quick, I wanted to throw now you mentioned type inference and before I forget, I'm curious how far that could go. I know Scala has a lot of issues with their type system because they've got sub, you know they try to do inference with sub typing in that,

ANDERS: Right.

BRIAN: But I'm curious with JavaScript, especially-

ANDERS: Well, I mean, I think that the one big difference between pretty much all the languages that are mainstream and TypeScript for example is that TypeScript has a structural type system not a nominal, not a class-based type system. And that changes a lot of things. You know, in a sense it's formalized duct typing. You know, you can say, "Here's an interface or an object type with two properties foo and bar." And anything that has a foo and a bar satisfies that interface and you don't have to first up front declare that it satisfies that interface, it just does, structurally. And that changes profoundly how a type checker works. And it makes it a lot less intrusive.

I mean you often find in C# and Java that there's a lot of ceremony that you have to do up front and if you didn't do it up front then certain downstream things don't work, like "Here's this class that didn't say that it implements this interface and even though it kind of does, I can't like make it do it other than by writing an adapter and a forwarder and a thiser and a thater." And do you know what I mean? That very quickly you get a lot of complexity. And so I think structural is one key difference and I think type inference is, it's really the thing that powers all of it. Without type inference this wouldn't work at all. And both Flow and TypeScript rely heavily on type inference as the thing that actually makes the medicine go down, you know? I think without it, it just wouldn't look like JavaScript anymore at all and it would be a painful place to be.

JEFF: Yeah and one way that I like to describe inference is when you infer a type you're asking the system to understand what you're doing for you and when you write a type or notation you're expressing. So it's really a difference sort of between do you want to express what your expectations are or do you want the system to determine, to like to, to infer, to understand to look in and understand the system? And so you know when you think about annotations versus inference in that sense, you get sort of a different perspective on when inference is useful and when annotations are useful.

BRIAN: And just carrying that extra meta information around for your type, is there any way, I often run into issues where I'm porting something from like Haskell's type system where you know, you can tell it what interface to use and it will just kind of pluck it out of the ambient environment. And with JavaScript that extra information is not really available at the, you know, the value level. And I guess that, how far do you think you can take typing, like, are we gonna be able to do like type whole driven development eventually or do you think we'll be able to have higher ranked kinds? What is the ultimate type system we're shooting for?

JEFF: There's some limitations you get, like I think, so both type systems as far as I understand are now, definitely Flow and I'm pretty sure TypeScript as well, correct me if I'm wrong Anders, are exclusively, like they don't deal in their run time. So they're dealing statically entirely. When you start dealing with these like higher kind of types and a lot of these really advanced type system features, you start needing the type system to actually feed into the run time as well, and I think, I don't know--

ANDERS: Well, so when I think of high kind of types, I typically think of, you know, can you, can you have type parameters that take type arguments? (laughs) You know, that's higher kind of types, and it's sort of like the ability to construct monadic things you know, that, "Here's this pattern but the pattern itself is further parameterized and how many meta levels can you go out?" You know, it's hard to reason about, it's hard to construct type systems that do this. And we have a little bit of higher kindedness but not a whole lot. And honestly I think it's just sort of a popular thing to talk about, but in real world programming it doesn't show up all that much. If it did, we would have heard more about it, I think.

I wanna go back to one other thing you mentioned by the way about how far do we think we can go? You know one of the things that we knew from the onset of designing TypeScript was that we were never gonna, the entire world is never gonna be TypeScript. So we have to coexist and we have to be able to leverage all of the existing efforts that are out there, or not we, but our users have to be able to, you know, meaningfully use other frameworks that were not written in TypeScript. And that's why we invented these things called declaration files which you can sort of think of as the equivalent of header files if you will or the ability to, after the fact, write down the type information for an existing framework. And then have the compiler slurp that up, and all of a sudden know a bunch about what JQuery does or what Lodash does or Reactor or Angular or what have you. So we sort of have the ability to both code, you know if you're using a library, say like Angular 2 that's written in TypeScript, then, well, the type information basically is there already, right? But if you're using something that isn't written in TypeScript like Reactor or whatever, well then, you can produce a declaration file for it and then get exactly the same experience really and without really knowing, you know, program without it affecting your development experience. We're actually in TypeScript 2.0 we're using Node as the package manager for external typings as well, so you can now, just like you can npm install Reactor, npm install Lodash or JQuery, you can also now npm install the types for those if they don't provide them themselves.

KENT: That's cool, so, how is that done? Is that just like somebody in the community publishes those types themselves? Like how do you manage that?

ANDERS: Well there's, there's a site called, you know, shortly after we released TypeScript someone created a type site called DefinitelyTyped, Boris Yankov was the original author of that. And that's sort of been the gathering ground for external type information. There are about or actually over 2,000 different frameworks are now covered or 2,000 declaration files up there. And the latest stuff that we're doing in TypeScript 2.0 we will actually now auto-publish npm packages out of the Definitely Typed repositories. So anything you upload up there, whenever a, we basically listen to that GitHub site with a hook and then whenever things change, we auto-publish npm packages or we will by the time 2.0 ships which is shortly.

JEFF: Yeah, this is a really important, I think feature especially for, like you said, like when you talk about typed JavaScript you have to acknowledge that JavaScript is not typed, these are tools, and so you have to be able to integrate with the actual JavaScript ecosystem, that's one of the powerful things is the ecosystem. So having these interface definition, you know, repositories is huge, we've been working on this as well with Flow, it's something that you know we think is pretty important for being able to not just allow consumers to maintain the utilities they're using from npm or whatever, they're using them correctly, but it's also actually really important for authors as well to be able to publish the things that they've already verified about their programs and when consumers consume them they can use those verifications as well and sort of the glue code as Anders was saying is this like concept of a library definition. And so yeah, I think having these library definitions out there and having them sort of community managed is like strictly important for the growth of typed JavaScript.

BRIAN: If I want to pick up Flow or TypeScript today, how do I get started? (laughs)

ANDERS: (laughs) Oh God, I think the answer's pretty similar for both of us, go to typescriptlang.org is where I would start and there are links to everything there. And then I would highly recommend also trying it out with Visual Studio Code if you don't already have a favorite IDE. Although I will say that we, we've engineered TypeScript such that it can be plugged into pretty much any IDE, earlier you talked about WebStorm, they have TypeScript support for example. We have plugins for Sublime, VIM, Emacs, Atom, you name it, likely there's a plugin for your editor that supports it. And, actually technically the thing that's interesting about it is they really use exactly the same code that we use in vs code. So the way VS Code gets all of its statement completion and refactoring and all that stuff is by running and out of process thing called TS Server, that is sort of the magic oracle that sits behind the editor and coughs up all the right answers very quickly when you press doc and it showed if you need to know what can go here, that's the thing serving it up. And it's exactly the same thing that sits behind Sublime text or VS Code or Emacs or whatever.

JEFF: Yeah, basically the same story for Flow, it's like, if you go to the website Flowtype.org is there's a getting starting guide there. We're a little further behind on the IDE integration. We have integration for a lot of the big IDEs. We have integration for VS Code and for Vim, Emacs and so on. But basically we're sort of working on editor integration right now. We have most of the APIs sort of fleshed out we've been working closely with Nuclide to kind of get that.

But yeah I think, (laughs) oh, I know what I was about to say. Basically the getting started workflow is, for Flow at least you basically just create a file called flowconfig in the root of your directory, and, there's a command called flow and it basically creates it for you. And the general direction, the workflow for getting started is you do that in the directory of JavaScript files and then as you were ready to sort of incrementally add those files into the type system, you go and add this @flow comment at the top of those files. And so that's where the getting started (mumbles) with flow.

BRIAN: To just to get the actual type definitions, though, for the libraries, like, you know, I have an app, right? And I'm not starting from scratch, or even if I am, I still need to get typed definitions for all of the libraries I want to use unless I just want to type them as object. (laughs)

JEFF: Yeah, true.

BRIAN: Any, um, so how do you recommend finding those or going, I know there's definitely typed for TypeScript but for Flow is there a repository yet or like a shared community?

JEFF: Yeah, there's a repository and a growing community, we call it FlowTyped, it's on GitHub, you should be able to, I think there's a link on FlowTyped.org, if not, I'll make sure there is one soon. And it basically has a CLI, you can run MPM install and then you run FlowTyped install. And it actually, we're in the process of launching this, we're sort of aiming to launch at the end of the month more broadly. But right now you can explicitly list the lib defs that you're looking to install and we're hoping that you know by launch time, we're gonna have it so that it can actually read your package JSON and install the lib defs for you.

BRIAN: Oh, cool.

JEFF: Yep.

BRIAN: That's pretty sweet, I like that. And so like, oh wait, Kent's had a question before I started blabbing.

KENT: No you're good. I just wanted to say it looks like Anders magically turned into Dan. (laughter) But no, hopefully Anders will be back, just having problems hearing us, but yeah, welcome Dan, good to have you here.

DAN: Hey.

KENT: So yeah, I did wanna ask a little bit like in the same vein as like getting started and stuff especially when you have an existing app, like all these, these alt JS languages or these super set of JavaScript or whatever you have, like, obviously these are not things that will be run in the browser. I shouldn't say obviously, but yeah, these things won't be actually run in the browser. So there's some tooling that you have to put in place, some costs that you have to incur to get, you know, these benefits. And we've talked at length I think about the benefits of typed JavaScript. It seems really beneficial, like why wouldn't you want to do this? Can we talk a little bit more about the costs associated with this and maybe that will bring to light some of the, some use cases where you might not want to use typed JavaScript. So what are some of the other costs associated with bringing types into JavaScript?

JEFF: Yeah, that's a good question. So with both systems, with both TypeScript and Flow, you've got type annotations that are gonna come with, that's how you sort of express these types. And that means we're sort of extending the language a little bit. And that also means that you're going to need some sort of compilation system or transpiler to pull those things out before you actually run the code. So in the case of Flow, we sort of pair with Babel to do that, so whenever you use Flow typically you're also going to be using Babel as well. In the case of TypeScript, they have their own compilation unit, so that has to sort of be integrated into your build system as well. So I'd say that's sort of one downside, I guess. I don't, I think as Babel goes on, you know, the cost of introducing Babel into your system, at least I, in my own experience, other people may disagree, it's sort of the cost has been driving down, so hopefully that's not too bad. I think the other cost to this is of course sometimes when you want to be able to statically reason about a programming language as dynamic as JavaScript--

ANDERS: Alright I'm back.

JEFF: Anders is back, can you hear us?

KENT: Yay.

BRIAN: Yay.

ANDERS: I don't know what happened there, but--

JEFF: Cool, just to bring you back up to speed, we were talking about some of the caveats of typing JavaScript. So we were talking about sort of the build system aspect and how it sort of introduces a build system where as if you don't have, if you have like a really small project it may not be worth it.

The other thing I was going to call out was, oh, when you right type JavaScript you're asking, especially with statically typed JavaScript, you're asking these systems to reason about your program statically without running the code, and that does mean that there are some circumstances where the system is not able to fully extract what something does. For example, it's actually really hard to come up with good, realistic examples of these, could go with contrived ones pretty easily but, you know, you could set some value and some object in one function and then read it in another. And the system may have trouble determining what order those two things come in so it may ask you to sort of rewrite it in a different way. So yeah, I mean that's definitely also another trade off you get with these sort of static reasoning systems is you're sort of trading off the ability to write any code for the ability for the system to reason about it for you and help you to ensure that you're not making mistakes, even though maybe you're not.

DAN: I have a question about Flow. So as far as I understand it like the, one of the benefits of flow is that you can gradually introduce it to the existing code base, but something that I hear from people sometimes is that the problem is it's hard to tell if Flow actually enforces some things. So you may have some code that you think is going to be type checked, but actually Flow can't determine that like this thing is that thing and so it doesn't do the type check. So how does Flow deal with that?

JEFF: Yeah I mean, one of the most common sort of issues that we're sort of trying to circle right now in the team is people forget to put @flow at the top of the file that they think they had @flow at the top of. And @flow, when you put just comment with @flow at the top of the file you're basically explicitly opting in to type checking for that file and the whole approach there is you can the existing code base and sort of module by module opt in to typing one at a time as you go and all at your own pace. But sometimes people either start with a brand new project and they don't have @flow at the top, or they, you know, assume that some file in their code base that is progressively typed has @flow and it doesn't. And in the case where @flow, where a particular module is not type checked in Flow, that's the only case before actually assumes any. The other thing, anywhere else in typed code with Flow, Flow never actually pulls any out of nowhere. So as long as you have @flow at the top, you can be certain that Flow is type checking your code, and anywhere that it's not, but it's gonna give you an error and tell you. There's actually an ESLint rule out there that somebody built that helps you reminds you to put @flow at the top of your file, so, that's really useful and I could probably link to that for the show notes.

ANDERS: Yeah it's sort of a like good point on how that works, in that, in TypeScript if you can have JavaScript files in your project and those we don't check or we don't give you errors in your JavaScript files, but we'll still pick up some stuff from them, you know, like if you have top level function decorations or whatever, we would understand there are functions but we obviously don't understand what types or parameters they expect. But, but in a TypeScript file, we will check and we give you sort of options to have different levels of checking and then in fact there's one option that many people use called no implicit any. And once you turn that on, then we will never implicitly infer no type. And at that point also you know that if there are anys in your program, it is only because you put them there. And presumably you did that because you knew what you were doing. And that also means that your refactorings are gonna be safe if you do refactorings.

The thing that's interesting about typed JavaScript is I often say that it turns typing from a switch, from being a switch, and on off switch into being a dial. And you can put the dial where ever you wanna put it, and the more you dial it up, there may be some extra work, but then there are also some extra guarantees that come out of it. And it's actually quite useful in a hybrid universe like JavaScript to have different dial settings for different parts of your program, particularly as you're easing into it. And that's certainly something that we see a lot of people do now, you know, have these mixed projects where parts are TypeScript and other parts are not because, well, we're not touching that coding, right now and it works and so we're just gonna put that over here and write a declaration file for it, and then, you know, write TypeScript for the new stuff for example.

BRIAN: Yeah, that's actually exactly what I was gonna ask about is how do you get the most out of the type system? I know in certain languages people are trying to banish strings right, they want everything to be in a new type wrapper, you know, they just don't want anything typed as a string, and that really helps a lot. So when we get into like getting the most out of your type checkers, is there a specific pattern or path to get to that third dial that you recommend or (laughs)

ANDERS: Well I mean as I said, the one thing I would tell people to do there is to do the no implicit any compiler switch because then we will literally complain everywhere that we can't find, figure out what the type is.

JEFF: Yeah, I mean, one sort of piece of advice that we often give and I'm on the same lines as like, we don't have an option for no implicit any, but, sometimes people will write any. And that's a temptation. It's actually, there was a really good talk on this from, the name is escaping me, about a year ago, about how these gradual type systems sometimes fool you into feeling safe. You know, you have this easy out, that you can always write any. Try not to, like really try hard not to write any when you have that option. Sometimes you have to write any and get on with it. That's definitely something I would encourage people to avoid doing is writing any. And really, getting to that third dial in TypeScript or Flow, we don't really have this level of dials. We sort of use inference to kind of drive to one mode in Flow and we assume that you're opting in module by module and as you opt in each module, you're sort of locking that module into safety. But as you go through and sort of type your program, avoiding these anys and avoiding these like types that aren't safe is probably the biggest thing to get yourself, to get the most out of these type systems.

DAN: Something that confused me when I just started looking at Flow is the difference between mixed and any. Can you explain it?

JEFF: Yeah, so mixed has the any type which is the same actually as in TypeScript, I believe. But there's also this other type called Mixed. I think James Kyle is actually writing up a blog post on this that should go out soon, he did a really good job of explaining it, so, I'll try to do a TL;DR. And then hopefully he'll publish that soon, and you can refer to that. But basically mixed, in type terms, mixed is the super type of all types. That means anything can flow into a mixed, but nothing can ever flow out of a mixed. So if you have a variable typed as mixed, if you ever try to assign to it that's always, that is always okay but if you ever try to use it, say as a number or a string, that's never okay. It forces you to, like, prove that it's a string or a number by using type or whatever. With the same analogy of going in and out, you know, if you put a parameter on a function as mixed, it means you can pass anything into it, but within that function, you have to prove for what kind of type it is, with type of (mumbles) for instance and so on.

DAN: Does TypeScript have anything similar?

ANDERS: Yeah, it does, it's well at the top level, but if you write curly, curly, (laughs) that's basically the same as mixed. It is like, it's the root of anything. Because I think we have a different viewpoint on whether primitives are assignable to the root type or not. The thing that's interesting too is that that in TypeScript 2.0 now where we have control flow analysis and strict malleability checking. We also have a new type called never which is the ultimate bottom type, the type strangely that is assignable to everything and nothing is assignable to it. (laughs) And it's this oddity of a type that pops out when the type checker proved to itself that this variable is never accessible or this function never returns for example. And sometimes you know when you have a never and your union it together with other things you actually want it to just evaporate and go away. Because you can say, if you have a result or a function that never returns and a function that returns a string, well that should be a string right? Because the one that never returns, well that never returns so it shouldn't add any type to that union. So there are some funny types like the top types and the bottom types in both of these type systems.

BRIAN: So yeah, that gets to kind of the algebra of types there. And I'm curious about sum and product types, am I able to achieve that in TypeScript?

ANDERS: Yes, although we call them union and intersection types but yes. And with TypeScript 2.0 we also now support discriminated unions where you know, it's, in particular when you're doing like functional programming with abstract data types or sort of the JavaScript equivalent of abstract data types where you have a tag in your object that says what kind it is, and then depending on the kind, you have different other properties in the object.

BRIAN: (coughs) Redux. (coughs)

ANDERS: Which on the kind, now inside each case we'll then already know that your reference to your object now has the correct type or did you guys already discuss this? (laughs) One of the things there that's interesting too is that because of the network type, we actually can do exhaustiveness checking as well which is important in functional programming languages. You wanna make sure that you covered all cases and you wanna get an error if you didn't. And we've got that pattern covered also now in TypeScript 2.0.

JEFF: Yeah, talking about those, the discriminator types, that's something that, you know, one of the actually driving cases for us to add that was GraphQL and ultimately Redux. Both of those systems are dealing in patterns that are really well suited for that, you know you have this object with this kind, you want to be able to take a union and separate them.

ANDERS: Yeah, or any message processing app, right? Which all micro services tend to be, right? They get a request and there's a certain number of requests and then each request has a different pay load, and you wanna sort of switch on that and then do whatever, right? I mean and you wanna check that you handled all of the possible requests. So if you've written down type declarations for that, we can now cover those patterns, yeah.

BRIAN: One more question just to throw in there, before I'm done for the day, (laughs) and let other people talk. Just, you know, there's stuff like covariance and contravariance, and you just mentioned that some are products which I can totally achieve, but, what features should we look forward to in both of these type systems that might be coming out soon? I'm just curious.

ANDERS: (laughs) Well the co and contra variance is actually, I think Flow has some of that now, right? And we've looked at it, I don't think we're gonna go there. I've been there before with C# and Scala and whatever and it's, it's one of those where, you know, boy, it is, it gets painful when you start dialing in co or contravariance and it gets hard to reason about. And sometimes the complexity is just not worth the, I find. But, I mean, you know, there are so many things that we could keep looking at like common patterns in JavaScript doing like promises or whatever. We're doing async programming, you know, there's like interesting patterns coming out around that. So, I think in general, we, with TypeScript 2.0, we've gone a long way with control flow analysis and malleability checking, discriminated unions, and types delivers as npm packages, I would say are some of the highlights and we're about to ship that in just a few weeks.

JEFF: Yeah, I mean, so, as far, yeah the variance sort of rules, we've adopted, we sort of have strict variance rules. A lot of those stem from mutability aspects of the language, like if you have an object and a property that is writable, then if you don't carefully, you know, control for variance then it's easy to have your type system think that a property is one type but it's actually another. So that's one of the reasons. And it actually kind of goes into like a little bit of differences in philosophy here I think that's maybe a good example, sort of, Flow really is about sort of deeply understanding your code and that means that it is going to enforce this level, and TypeScript is so about the tooling aspects.

The other, as far as like features that you know, you're looking forward to, like one really, one feature that I'm actually really excited about, we have somebody on the team working on, it's actually, TypeScript has this now and we've sort of taken it and run with it, I think it's a really cool feature, predicate types. They allow you to say effects that happen as a result of a function. We're sort of running out of time so I don't have a ton of time to go into this, but I'm really excited about that. We also have some other features coming up pretty quickly, exact object types that are basically, they don't deal with subtyping. And that unlocks a lot of some of these issues with a variance also that you run into as well, if you say that, you know, a given object type has (mumbles). So those are two things that I'm pretty excited about.

KENT: Sweet, I love that this area is always progressing. And one of the cool things about the JavaScript community is that there's just so much that can be done and so like getting involved is, you know, there are a lot of opportunities and I think that's cool. So I had one other thing that I wanted to ask before we get into the several Twitter questions that we have, and that is like from my perspective, I have been nervous about jumping into TypeScript, because for the last year and a half I've been using Babel and ES Lint and just totally loving the plugability, especially since Babel 6 came out, like the plugability of those systems, and moving over the TypeScript I'd have to kind of give those up in favor of TypeScript and TSLint. Which means,

ANDERS: Oh, no. Not at all.

KENT: Oh yeah, so that's what I'm actually asking, because I want to be corrected. So let's hear about that.

ANDERS: Well I mean we've, so, TypeScript, we've always sort of had the viewpoint that most people want us to cover end to end. They want to write their code and then they want to say compile or not even say compile but have the compile happen automatically and then they just want to run. And they don't want to think about it. That sort of the default modus operandi of what we deliver. And so TypeScript can take you all the way from a writing code in my tool, it's delivering statement completion, refactorings and whatever. It can go all the way through the type checker and there's also an emitter that can emit and you can down level emit to any target you want, you know, ES5, ES3 or whatever or just stay at ES6. Now, if you wanna use Babel, for example, and in that pipeline we have lots of users that do, then you simply tell TypeScript to emit ES6 and then you run that through Babel to get your down level if you wanna use Babel for your down leveling.

KENT: So actually, just on that though, there are some like stage features of JavaScript, the language, that require parser changes, which as far as I'm aware, TypeScript isn't always that up to the standard that Babel is on. And so if I'm,

ANDERS: Well I mean, if, if you're talking about like features that are stage 2 or 3 or whatever, well no, but none of us are really fully up to anything (laughs) because they're not JavaScript features yet. So yes, there will be differences between, I mean, we may not have object spread in rest yet, but we will obviously, you know once it reaches a high enough stage. Typically, we say stage four for sure, we will be there. Some of these things are very speculative like the binding operator for example, you know, and who knows if they're gonna happen and then what do you do then if they don't happen, right? So, but certainly, anything that's in the standard we absolutely do support. And we support a lot of things that are on it that are weighing into the standard.

KENT: Okay, yeah so, for me it's that stuff as well as, because I do use some stage two features and really enjoy those and, also like the enormous community of other plugins for Babel as well as ES Lint. I think maybe I've sunk myself too deep into that community to really, to move over to TypeScript. But I'm probably not like your target user in that regard and maybe most people aren't quite the same as me and are happy to use--

ANDERS: It all depends on the size of the project and we're not trying to like own the world or whatever, we're simply trying to do good and trying to create something that is useful for a large number of users. I mean, when I look at our adoption numbers and whatever it seems like it is. I mean, certainly we've got lots and lots of usage and more people are coming, but if you're writing something that isn't very big or if you're working by yourself on a project and you know the entire thing you're doing, then these refactorings or whatever may not be so hard to do and I might not need these capabilities, you know? But if you're a team, or if you're trying to document your code or if it's a very large code base, you know, it, then, the reasoning simply looks different, right? And then it may actually be worth it to invest in using a type check.

KENT: Cool yeah, that's perfect, that's, and actually a couple of the Twitter questions, that kind of addresses those. So that's great, thank you. Let's move into Twitter questions, we're definitely gonna go over on our time which we do quite often I'm afraid, (laughs) but this has been a really great conversation, I wish we could keep going. But yeah, let's jump into these Twitter questions because people are asking useful things I think we should talk about so, Jamund Ferguson, a friend of mine asks, "What sort of collaboration is happening between TypeScript and Flow?" Is there any collaboration going on between these type checkers?

ANDERS: Jeff you wanna? Or I mean, we talk. (laughs)

JEFF: Yeah, we talk on occasion. Yeah I was gonna say, I mean we've sort of talked about sort of topic, like one topic that we've talked about in the past was library definition, like whether we could standardize those. And I think that was, that's sort of a tricky discussion when you get into the depths of it, part of the trickiness that goes into that discussion is like what happens when one system has one feature and the other doesn't? For example, for a long time, like TypeScript had predicate types and we didn't, so does that mean that they just, you can't write predicate types in decoration files? Or does that mean that Flow has to like sort of consume them and do nothing with them? And if we, if the former, does TypeScript have its own decoration and it's a universal? At which point is it better just to write the TypeScript one if you're just using TypeScript? So there's a lot of like integration points that go through lib defs that actually become not great when you really sort of think through the details of them. Otherwise, I think like we're both involved in like TC39 so there's always discussion going on in TC39 about you know, well TypeScript did this and it worked really well and Flow did this and it worked really well. And that's like, gets echoed between the two teams as well. So yeah, I mean there's some collaboration going on there.

ANDERS: Yeah, I would echo that yes, TC39 is definitely something that we're all involved in, Brian Terlson actually who chairs the spec right now is from Microsoft, and we, we're always like understanding what's going on there. And that's sort of how the core language evolves. And around the typing aspect of it, for sure the thing that would benefit the community is to have an agreed upon declaration file format. And I actually think it's entirely possible to do it and I'd be happy to participate in that, I mean we already have like an enormous volume of declaration files out there. So my primary concern would be to not invalidate what the community's already done and just make sure that that all still continues to work. But I think it's possible to do it if we were to put our heads to it.

KENT: Yeah, I think that's a fantastic area of collaboration, which would really benefit the community a lot, so, keep it up. You're doing great. So, we do have, oh man, several other questions but I think that I'm only gonna get to two more of these. So, if you all want to check out Twitter later with the hashtag #jsAirQuestion I'm sure these people would be grateful to hear answers to their questions. So another one that I wanted to ask is from Gil Christensen, "When do you think adding type check pays off the most? Big, small, medium sized projects, all projects or maybe just a certain type of project?"

ANDERS: Well, I think, my sort of stock answer there is, the bigger the project the bigger the payoff, you know. And as you've guessed you get more and more lines as you get more and more actors involved in a particular project. There comes a point where I would almost say it's downright crazy not to use a thing like TypeScript because, you know, it just, you're just wasting too much productivity otherwise.

JEFF: Yeah, I would echo that, I mean, I think the area of small where it doesn't necessarily payoff is the area where it doesn't actually pay off to set up all of the, you know, build system, you know all the structure around a project that typically you need at a larger scale. And those two things kind of go hand in hand, so if you have a good grasp on well I'm just gonna write a quick script, maybe you don't type it but if you're gonna write something that, you know, three or four people are gonna be using for a long period of time or contributing to, that's where you start sort of like having that discussing to make and deciding do I wanna add more, you know, utility to this or is it not worth it? Can I just like keep it all in my head?

KENT: Totally, that makes total sense. My last question, this is another one from Jamund. I wanted to talk about this during our chat anyway, he says, "How likely is it that a future version of JavaScript will have types?" I know we're not talking like actually, you know, explicit type definitions, and what do you think that would look like?

ANDERS: Well this is something that's been discussed many times even in the committee. And I don't know that there's a consensus in the committee that JavaScript will get static types, you know. There's been some talk about maybe having the ability to at least ignore type annotations if they're present. But the issue with that is, then, how do you standardize a system where you can say, let X colon string and then S equals 5 on the next line and it's not an error, you know what I mean? (laughs)

JEFF: Yeah.

ANDERS: It's very, it's hard to find a happy medium there. And I think trying to standardize the semantics of a type checker is, it's not for the faint of heart. I will argue that, you know, TypeScript type checker and the Flow type checker, no doubt, are fully as complex as a JavaScript VM implementation is, and if you have to write down all of the semantics of every corner.

JEFF: Yeah.

ANDERS: I think for standardization the thing that would make the most sense actually is to find and agree upon declaration file format. That's the thing that would mostly benefit the community, that is my cent.

JEFF: Yeah, I mean this was actually one of our first collaboration points between the two teams, when Flow sort of first came out, it was how can we come to the committee and sort of start talking about whether this makes sense? And one of the first things we talked about was, you know, well, just, you know (inaudible) syntax, type annotation syntax, and the pushbacks on the committee on that, and I think they were right and I totally agree with Anders here. To standardize these syntax annotations that mean nothing it means you can never standardize what they mean because anybody could have written them to do anything before. (Anders laughs) So what we did end up doing at TC39 is we said okay, after certain parts of the language in the syntax of the language, we're going to basically say, "You can't put stuff after a colon there." So actually if you go and you look in the ECMAScript, the JavaScript spec, you'll find this, there's actually a constraint as of ES6 that says after colons, after identifiers, are reserved space. And that was sort of the first collaboration, it's a tiny little part of the spec but (inaudible) good. It sort of guards us both to have this exploration (mumbles) space.

But it also sort of points to the fact that both these systems are like super-hot right now, we're sort of like innovating like crazy. Both of us are coming up with new features as we go and as new things come out and JavaScript idioms come out and finding the right way to do this. You know, like we have two different approaches, but, it's not like one's necessarily right and the other is wrong we just sort of like both tackling this. And so it's very early to come along and try to like set a standard on these things as we're still like discovering what it means to add gradual static types to the language of JavaScript. It's something that really kind of hasn't been done very well before, nothing I can think of. So yeah I guess Brian, bye Brian.

ANDERS: Bye Brian. (laughs)

JEFF: But yeah, so in terms of like getting as a language, maybe one day but like I can't, I can't see it in the near future. There's just too much to like, there's too much going on right now, it's not-- Brandon Ike likes to say, you know, sort of standards follow practice.

ANDERS: Yeah.

JEFF: I don't remember the words exactly but I kind of generally agree with that, it's like, once you've sort of found what it should be, then you should standardize it. I think it's kind of too early.

ANDERS: Exactly.

KENT: And I appreciate tools like Flow, TypeScript, Babel, for making it possible to test things out, to make something a practice before it's a standard. So, it's a wonderful time to be alive as a web developer. I love it. Cool, so, that's all that I have time for these Twitter questions. Let's jump into our tips and picks and then we'll wrap things up. So, I'll go ahead and go first. So first my tip is, no matter how well you know something, keep your mind open to learning even more about it. Like, I feel like I actually had an example in my mind when I wrote this down but now I've forgotten it, but I think it's a good tip. (laughs)

I have three picks, first React Rally 2016 notes wiki. This is a Google Doc that the community has built up for notes about the React Rally conference that happened last week which was fantastic, so I recommend that you check it out, yeah, really, really good talks there. And then tomorrow, Dan and Ben Alpert and I are going to be talking about React events in depth. And it will be live and it will be kind of similar to this show actually, as far as just having a conversation about something. And yeah, we're gonna be talking about how the event system in React works, should be really cool. And then Husky is an npm package for shareable Git hooks, it uses package JSON npm scripts. And yeah, I normally, for all my projects before I've used ghooks, which is another similar package, but I saw Husky, I haven't tried it yet but it looks awesome and it seems to have a couple features that ghooks is lacking. And so I think I'm gonna give that a shot. I thought I'd give it a shout out.

So I'll actually read Brian's tips and picks because he had to jump off. So first for his tips, he has two functions, should be input to output. Type systems help a lot more when you can post this way. So I think that's like, don't just have a function, do side effects like, give it something, get something back, that's nice. And then stay away from object and any types. (laughs) That's a good tip. And then we've got two picks from Brian, first John Sterling at Lambda Conf 2015. I think this is a talk called Type Theory and its meaning explanations. And that's a YouTube video. And Chris Taylor, I think this is, yeah it's a blog post. Chris Taylor wrote a blog, algebra and algebraic data types, so, check that out. Alright Dan, do you have any tips and picks for us?

DAN: Yeah, I do have one pick. I don't actually have a URL because my pick is a blog post that is not out yet but is going to be out like today or tomorrow. This is a blog post by Christoph Pojer so he was working like crazy on the new Jest release, the Facebook testing utility. And it's got like a massive overhaul, all the crazy features like auto marking that people didn't really like in the open source are disabled by default now. And the UI has received a lot of improvements, so just check it out. It'll be out tomorrow, yeah I think it's gonna be great.

KENT: Well cool, I'm so looking forward to trying out Jest now. I feel it's gonna be great. Cool, Andre, do you wanna, or Anders, I don't know why I called you Andre--

ANDERS: Well, I'll just say, you know as a personal thing, programming has always been my passion and I always urge and tell people, follow your passion, go play, go write some new code or whatever. That's how you do your best work. It's like always try to be passionate about what you're doing and try to enjoy what you're doing.

When it comes to tips I think, you know there are a lot of people coming to JavaScript now because JavaScript is sort of the only cross-platform game in town and a whole bunch of client apps are being written that way. We have lots of hoop programmers flowing into the JavaScript ecosystem from say C# or Java or you know all sorts of other programming communities. And one of the things that's interesting about JavaScript is that it has, it has great support for programming with functions and doing functional style programming. A lot of people are surprised when I tell them that the TypeScript compiler doesn't have any classes in it at all. It is all written as functions and functions within functions. And of course we have a bunch of interface declarations because that's how we declare our shapes of our objects, but, a lot of things are possible to do in ways that you are not accustomed to and not everything in the world is a class. So there's a lot you can learn from studying functional programming and even in JavaScript. And I would definitely recommend that people do that. I've learned a lot myself. (laughs)

KENT: You would get like a giant cheer from Brian if he were still here. (laughs)

ANDERS: (laughs)

KENT: Functional programming is his jam. Cool, Jeff?

JEFF: Okay, so I guess we'll start with tips. So, I think there's this sort of strategy that I've used for a while and kind of lost touch with it and recently had been using it again when it comes to doing, sitting down and like working on a big project which is like, sometimes I get hung up on just trying to figure out how it should be in the correct way, like how do I do this correctly? And that's not a bad intuition, but sometimes when you're facing a big problem, for me it's really useful to just, take the approach of you know what? Just get it working, doesn't have to be perfect, doesn't have to be good, just get it working. You'll clean it up, right? Once you know that it works, then you're gonna be invigorated and excited and you're gonna go make it clean and maybe you have to rewrite it but whatever, now you know how it works. So this whole like just get it working mentality is something that I think is, that's gonna be my tip for today. Don't like leave it in a mess, but you know. (laughs)

Anyway, as far as my pick, I'm gonna pick OCaml and Reason because I think that they're languages that are scary to some people and it's something that I came to only a few years ago and actually they're really interesting languages. And they're completely different, most likely completely different from what you've seen before if you're used to things like C and Java, and C++ and so on. It sort of like expands your mind to think about things this way and the really cool thing about OCaml and Reason is that there is high level languages that are designed so well, that they can compile down to something low level and run very efficiently. And so I don't know, that's just really cool to me, in my head prior to like exploring this space it was always like, we have high level languages and they're slow, you have low level language for efficient stuff. And OCaml is somewhere in between, it's sort of like, like Rust is sort of the latest incarnation of this concept too right? So yeah, so like OCaml is one of my picks. And along with that pick I would recommend this book, it's an online book called Real World OCaml. And it's not a text book it's like written in normal English so you can just kind of, you actually go read it from start to finish if you have enough time, it's not that boring. And so I have a link for that as well, it's kind of a fun learning opportunity if you haven't messed with OCaml before.

KENT: Cool, thanks Jeff. These have been awesome resources and tips. So, I like this section of the show, I think it has lots of good resources coming out of this. So, cool, so, just gonna wrap some, oh Dan, sorry.

DAN: Yeah, I have one tiny pick. I forgot about it. So I just bought this book, it's called the Grokking Algorithms and it's amazing, like for people like me who don't have computer science education, it's full of pictures, it's full of like really, real world examples that are simplified. So if you are scared of structures and algorithms, check it out.

KENT: Sweet, alright. Let's now wrap things up. So just, oh I totally lost myself in the doc, okay yeah, so we have a couple Silver Sponsors that we're grateful for, ReactJS program helps you to master the React JS ecosystem. And Sentry Cross Platform Crash Reporting so check them out. As always, I appreciate your suggestions and feedback, so go to JSAir.io/suggest to suggest episodes, topics and guests or both, and Jsair.io/feedback to give us some feedback on the show, really appreciate that. And then Jsair.io/email will take you to our email newsletter that we send out weekly right after the show, like the day after the show is published, with highlights and interesting information about the show.

So yeah, and then, we do have a show coming up next week, it's entitled NodeJS and Community, so looking forward to chatting about that next week, same time, same place. And as always, follow us on Twitter, Facebook, and Google+ to keep up with the latest. And in case you missed it, we are gonna continue doing the show for now. So, yeah, they didn't actually cancel Hangouts On Air, they just moved it, so, good stuff. Alright, that's it, thank you so much for coming on the show, Anders and Jeff! Really, really appreciate it.

ANDERS: You're welcome.

JEFF: Thank you, this was fun.