CoRecursive: Coding Stories - Tech Talk: Typescript with Chris Krycho

Episode Date: July 15, 2019

Tech Talks are in-depth technical discussions. How do we make JavaScript easier to work with? Chris Krycho has been using typescript to add types to javascript since 2016. Chris is a software develope...r at LinkedIn who, at his previous gig, worked on converting one of the largest Ember apps in the world to TypeScript. I was shocked by the size. Chris also loves Rust and types and is a former C and FORTRAN programmers. He hosted a podcast called the New Rustacean, which he has retired from. Today we talk about TypeScript and when you should use it. We also talk about Language Server Protocols, Rust, working with large codebases, Structural types, row polymorphism and talking code over audio. Chris's Blog TypeScript New Rustacean Chris's Typescript Refinement types in TypeScript Winning Slowly Podcast https://corecursive.com/034-chris-krycho-typescript/  

Transcript
Discussion (0)
Starting point is 00:00:00 TypeScript is the closest thing to dependently typed and refinement type systems that actually is in production at scale anywhere. It's not doing those things, but it's probably the biggest step in their direction that you're seeing in sort of industry use on a wide scale. Hello, this is Adam Gordon-Bell. Join me as I learn about building software. This is Code Recursive. That was Chris Krejcho.
Starting point is 00:00:30 Chris is a proponent of TypeScript, who's been using it since 2016. Today, he teaches me about what TypeScript is and why we should use it. Chris is a software developer at LinkedIn who worked on converting one of the largest Ember apps in the world to TypeScript. I was actually shocked by the size of it. Chris also loves Rust and types and is a former C and Fortran programmer. He hosted a podcast called The New Rustacean, which he's since retired, but was really well done. I hope you enjoyed the interview. And as always, thanks to everyone who has tweeted or blogged or otherwise mentioned and join the podcast. Chris, thanks for coming on the podcast. I mainly know you as like a disembodied voice that explains to me new features about Rust. But today, I'd like to talk to you about TypeScript.
Starting point is 00:01:18 I am glad to be here and looking forward to it. I will admit to have had the weird experience of walking into a meetup room and saying to someone, oh yeah, hi, I'm Chris. And having heads turn because they've heard my voice from Neuro Station. And let me tell you, that never stops being weird when people just hear your voice and turn around because they recognize it. So, disembodied voice on the internet is apparently my thing at this point. Yeah. Podcasts are a strange kind of intimate medium, right? Because I feel like from listening to your podcast that I know you, but you know, you don't actually know me. Right. But I listened to your podcast, so I have the same feeling. It's random weird.
Starting point is 00:01:59 So what's TypeScript? TypeScript is a typed superset. Technically speaking, that's not true. And I'll talk about that a little bit more in a minute. But it's effectively just a typed superset of the JavaScript programming language. And what that means is you are able to add type annotations to JavaScript. And then you have a compiler which can do two modes, one of which is just check that code, and one of which is actually generate JavaScript or that can include various feature proposals and the like. So a lot of places today will use TypeScript just for the type checking and then use Babel
Starting point is 00:02:51 to compile it so that everything's a single pipeline. But the big idea for TypeScript is to say that huge amounts of the web at this point and huge amounts of all of our infrastructure is increasingly written in JavaScript and in large JavaScript applications. And many developers find that with sufficiently large, sufficiently complicated applications, libraries, and so on, having a type system is a helpful tool. So the original pitch, possibly still the pitch on the TypeScript website, is JavaScript that scales. And the idea is you can gradually layer in a layer of types on top of an existing JavaScript application or library, or you can
Starting point is 00:03:33 use them from the start of building a new one and start getting some of the benefits that types give you. In particular, refactorability, because you can know rather than just guess heuristically where a given item is actually being used throughout your code base. And a certain degree of reliability, for example, things like null checking. You can tell TypeScript to, hey, check me and make sure that if this thing can be null, I check it ahead of time. And that combination of giving you some much more sophisticated checks on what you're doing, and then giving you tools for refactoring, means that at least in principle, TypeScript code can be much more scalable JavaScript in my experience. Now, there are a lot of my fellow JavaScript nerds out there who are saying,
Starting point is 00:04:23 ah, boo, you and your types. But for me, the experience when I actually started pulling TypeScript into apps and add-ons libraries that I was using was there were a bunch of places where I thought, oh, yes, I have exhaustively checked all the ways that this could possibly ever be null. And the compiler said, you're wrong. So the value proposition there is let's take this very dynamically typed language and give you the tools to describe the types you're working with and in very rich, sophisticated ways that do actually capture the incredible dynamicism that JavaScript has. And that's probably what makes TypeScript particularly interesting from the perspective
Starting point is 00:05:02 of type theory or something like that is JavaScript is a wildly, incredibly dynamic language, which you can do ridiculous, crazy things with at runtime. And TypeScript can actually represent in its type system, a very large and an ever increasing percentage of that. I hope that's a good rough start to it, at least answering your question. Yeah, totally. So if I understand, TypeScript, like the short version, it's types for JavaScript. So where did this come from? Microsoft started the project in the early 2010s, 2012, 2013, I think. And the lead contributor for it is Anders, I'm going to pronounce his
Starting point is 00:05:48 last name wrong. I'm so sorry. Helzberg? Helzberg? It's a name I've never actually heard, just seen on the internet. But this is the guy who was behind most of C Sharp. And before that was involved in, I think, Turbo Pascal or Delphi or both. I think both, yeah. Very, very important contributor to programming languages. And I like to joke that for good and for ill occasionally, mostly for good, but occasionally for ill, TypeScript seems like Anders' playground for interesting type theory ideas at scale. So came out of Microsoft, continues to be driven by Microsoft and is heavily integrated
Starting point is 00:06:26 into Visual Studio and Visual Studio Code as a result. A lot of Microsoft's own open source tooling is built with TypeScript at this point. I don't know his name either. Anders, let's say. I like his taste. I remember, you know, I did Java development for quite a while, maybe not quite a while, but then I switched to C Sharp and I was like, oh, it's like Java, but it's like, you know, it's kind of polished off. Yeah. They got some nice things that I feel like he's very pragmatic maybe. And now he approaches a language like, oh, we should have a way to do X. I think that's a very good description. And that pragmatism is both one of the things that has made TypeScript very successful, I think. And also one of the things that can drive me nuts on a day-to-day basis. Because, well, I like to call myself an idealist,
Starting point is 00:07:11 but we all know that everybody but the idealists likes to call the idealists impractical and so on. I tend to prefer type systems that are a little more rigorous and a little stricter and more sound in particular. The idea of soundness being that if you have a program that type checks is not going to fail in ways that contradict those type checks. So examples that many listeners will be familiar with are languages like Haskell or Rust or Elm. I believe Scala, though I would not quote myself on that, F sharp, et cetera. And TypeScript is not that and TypeScript has become much more that, but philosophically TypeScript is a deeply pragmatic language. And so the tooling and the type system around it are very much built on enabling and empowering
Starting point is 00:08:07 working JavaScript developers, which is a goal I can really appreciate, especially as someone who's worked in it day to day for a number of years now. But there are definitely places where I want to be able to say, no, check me. I don't trust myself. I'm an idealist. But what the idealism here means is that I'm a total cynic about my own ability to actually get this right. So please check me exhaustively and rigorously here, TypeScript. So is it not, this is a superset of JavaScript. So they're trying to
Starting point is 00:08:37 meet the JavaScript world where they're at? Exactly. And that notion of it being just a typed superset with only one exception, everything in TypeScript is just a type annotation, which you can strip out. And the only exception to that is the enumerated type it supplies, which is just like your basic enum from Java or C or whatever else, except that it can also have string values. But when you look at that, it just compiles straight into a simple JavaScript object with some key value lookup. So even that one technically breaks the everything is just a type annotation that you can strip out. It doesn't really break it. And so they really are just trying to say, we're not going to pull an Elm or a ReasonML with BuckleScript or something like that,
Starting point is 00:09:25 where we're creating a whole new language for which JavaScript is the compile target. Instead, they're saying, we're going to add types as a layer of very rich static analysis and tooling integration via the language server on top of JavaScript. But it's still just JavaScript with those type annotations in place. So like practically, okay, like I have some simple website and it has a bunch of client side JavaScript code. And then I want to take that and turn it into TypeScript. Like, what do I do?
Starting point is 00:09:58 You add TypeScript to your package.json and you type, you know, you run yarn or NPM install and you type TSC, which is TypeScript compiler in it. And it generates a TypeScript config file for you in the root of your project. You, depending on how you're building it, if you're using web pack or something, there are starter packs for that. Ember.js has a tool that I helped maintain in the CLI that just generates your configuration for you actually. So you could, in Ember, you would just say Ember install Ember CLI TypeScript. I think there's a similar just booted up experience for Vue and for Create React app where you can just say, Vue CLI start with TypeScript or whatever. But in general, you just add this tsconfig.json file
Starting point is 00:10:47 and tell it if you have any weird layout things, you have to tell it about those. But in general, if you're using a fairly standard layout for your file system, at that point, you're done. You can just start type checking. If you want to integrate it into your build pipeline, say you're compiling from JavaScript super fancy version next down to ES5 to run it on your build pipeline, say you're compiling from JavaScript super fancy version next down to ES5 to run it on IE11, which, hi, that's sadly still the story for many of us. Microsoft, please kill IE11. You'll use either TypeScript's own tooling to do that. The TS config that it generates will by default target ES5 and therefore be suitable for running. I think it targets ES5. It'll actually go all the way back to ES3, which runs on IE8, I think. Most people don't need that happily. You can either do it with TypeScript itself,
Starting point is 00:11:34 or you can just wire it into your Babel pipeline. And then you just start taking a file and saying, instead of ending this file extension with.js, I'm going to end it with.ts, just change the file extension. And by default, that's enough to start getting it type checked. It also actually has a comment style pragma that you can throw at the top of a JavaScript file where you type a comment and then say,
Starting point is 00:11:58 ampersand ts check, and it'll check the JavaScript file for you as well in sort of its loosest mode. So I'm not super, I don't know a lot of front end stuff. So I'm going to try to break this down because like, okay, so Babel is some sort of translation layer from magic new JavaScript to whatever I support. So let me take a step back. I live in this world every day and I forget that it is not the world everyone lives in every day. Because we are targeting browsers in general, we have to deal with the lowest common denominator of whatever browser we're targeting. And so while the JavaScript
Starting point is 00:12:35 spec continues to move forward and the language continues to move forward, unlike in a server environment where we can control exactly what version of a given language runtime we're running and can upgrade at our own pace. In the context of JavaScript, we may have to be targeting IE11. And Internet Explorer 11 targets the ECMAScript 5 version of JavaScript, and it doesn't have any features later than that. So although that came out the better part of a decade ago, and JavaScript has changed enormously since then, whether that's the inclusion of things like classes as syntax sugar for the function prototype way that you might have done things in the past, or the inclusion of constant let bindings, which have local better scopes, unlike the old VAR in JavaScript, which
Starting point is 00:13:24 gets hoisted and has weird scoping behavior that confuses people and breaks people all the time. Many new features like this, generators, async await syntax, et cetera, can all be carefully compiled back to ES5. If like me, you work at LinkedIn and we still support IE11. And so we need our rich client-side JavaScript to be able to run on IE11, even though current versions of Chrome and Firefox and Safari and even Edge before it shifted to being Chromium could all run stuff that's been part of the JavaScript spec even as late as the last year or so. And so Babel gives us this layer of being able to say, I'm going to write modern JavaScript with all of these language niceties, and then compile it back to an earlier version of JavaScript. So you'll often hear this referred to as transpiling,
Starting point is 00:14:16 because you're doing it not from targeting one language to another in the traditional sense, or a lowering sense, but from one language to another equally high-level language, which in this case just happens to be the same high-level language of eight years ago or whatever it was when ES5 came out. So Babel will do that. TypeScript can do the same thing and target an earlier version of JavaScript, or it can just target the latest version of JavaScript if you're one of the lucky people who can get away with shipping JavaScript that only targets current versions of Chrome and Firefox and Safari. So where does Babel run? Babel will run as part of a build pipeline on your, whether that's locally or in a CI setup or whatever else.
Starting point is 00:14:58 So most modern JavaScript rich applications, in order to be able to take advantage of all this functionality that we've built up, have a builds pipeline. And that's kind of weird in a lot of ways for people who are used to the old include a jQuery script tag and be off to the races version of doing front end web development. And for that reason, I'll frankly acknowledge that it can be a lot harder to get started in some cases, and it can feel a lot more intimidating because it's a case of, wait, I have to run this builds tool so that I can do some interactivity in my HTML page. And the answer is no, you don't actually have to do that. You can still just drop a script tag on your page and be off to the races. But again, for those of us building these rich applications, in most cases, we have command line tools integrated into that anyway, because we want things like linting to be able to say,
Starting point is 00:15:50 hey, here's some static analysis output, and to be able to run our test runner actively while we're going and developing the app, or to be able to do boilerplate generation of, hey, just give me a new React component or a new Vue component in my conventional locations for this app or things like that. And so... And I assume, like at LinkedIn, they're not letting you FTP some JavaScript file. No. And so we have a CI server where we're running all of that and running the build and running a large exhaustive test suite, and then generating those target builds back in ES5. And a lot of modern build tools can split it out and say, hey, we're going to generate a build for IE. And then we're going to generate much smaller, more modern, faster builds that don't do all that transpilation
Starting point is 00:16:34 for quote unquote, evergreen browsers like Chrome and Firefox and Safari, so that you can, again, get the benefits of an updated runtime that has support for these new features natively. Because when you are back compiling, especially something complicated like generators or async and await or things like that, you end up having to generate a lot of extra code to support that. And every app ends up having to make this trade-off of saying, do we use generators here? So for example, the app I work on at LinkedIn, when I'm working on this big app,
Starting point is 00:17:06 we don't use generators, because we have to ship this large runtime that basically acts like generators are part of the language by shipping it as a library. But that's a lot of code. And every byte you download and have to parse and then have to execute in the browser is a penalty to the actual runtime performance of your application. So we don't use generators in this app, even though they're really nice and make certain patterns really nice, because we don't want to support that back to IE 11. Makes sense. So a lot of people were already using a more modern version of JavaScript and then transpiling it. TypeScript steps in and says like, well, what if you add some type annotations?
Starting point is 00:17:44 Then when you try to add seven to undefined, then we'll let you know. Right. Or you try to call a function, it's undefined. And every JavaScript developer's least favorite, but most common error, undefined is not a function. No. TypeScript says, hey, we can just layer on top of this existing stack of tools that most of you are using and add this nice layer of static analysis and tooling support. And when I say the tooling support, the language server that they built around this is phenomenal. So whether you're using it in Vim or whether you're using it in Visual Studio Code, you get this really great experience for inline documentation and code completion and refactoring tooling,
Starting point is 00:18:26 all built on that language server. And it's a single language server, which Microsoft actually introduced as part of building Visual Studio Code and TypeScript support and integration back in probably 2013 or 2014, where they have this idea of instead of every editor having to rebuild its own tooling, you can define a common layer and then a common protocol for talking to that so that every editor can have a language server protocol implementation and just know how to talk to anything that speaks that protocol for any given language. And then you can have individual servers per language. And then you can fit those two together so that if Sublime Text has a language server implementation and Rust now has a language server implemented, well, those two can just talk to each other basically for free without either of them having to do all the work of
Starting point is 00:19:19 re-implementing refactorings for Rust. And then Vim gets that and Visual Studio Code gets that and so on. So that came out of the work Microsoft did for the TypeScript language server five years ago. And TypeScript remains kind of the canonical and best example of it. I didn't know that. Yeah. I think the language server protocol, it's like a game changer. So in my day to day, I'm using Scala. And traditionally, we always, you know, everybody used IntelliJ because it was kind of the only really good implementation. And now there's a language server protocol implementation for Scala called Metals. And just people are slowly drifting
Starting point is 00:19:54 off into using whatever editor they really want to use. Right. I mean, if I were IntelliJ, I might be concerned. But I think that, yeah, it's definitely an enabling force for languages, right? Like there's less overhead. Right. Because that cost of finding a tool that knows enough about and can introspect your code richly enough to do those kinds of refactorings and completions and all of that. And JetBrains' tools, IntelliJ and all of those, have always done very well and been very good at that. In my use of Rust, for example, I end up going back and forth because the IntelliJ Rust plugin and the VS Code plugin, each of them does certain things better than the other one or feels better than the other one. I like VS Code better.
Starting point is 00:20:39 It's a little lighter weight feeling. But the IntelliJ plugin is really good, and it's a little faster and more stable than the Rust language server. But that democratizing factor, I think you're exactly right, ends up allowing new languages to be adopted much more quickly. So another example of that, ReasonML is a syntax layer over OCaml that is primarily used for compiling to JavaScript via a OCaml to JavaScript compiler. But they built a language server. And I think it's actually just a standard OCaml language server that then can talk to VS Code or talk to Vim or whatever else. And it's the same thing. All of a sudden, all of that capability just exists for anybody that has a language server plugin. And that's a huge thing for somebody who wants to try using ReasonML, because the gap between that and whatever tool
Starting point is 00:21:32 they're already using is going to be so much lower than it would have previously. Yeah. So what do I get if I move to TypeScript, the language server protocol, what does it enable? So it enables refactoring. So it'll say, hey, I want to rename this type, this class, or this variable throughout my code base. And you perform a rename and it does it. It introspects your whole code base, finds everywhere that's used and does it with a rename.
Starting point is 00:21:57 Or you say, I want to find everywhere this is used throughout my code base. And whereas in a traditional JavaScript code base, you're left with doing that as your kind of best guess in your sort of heuristic driven approach, which can be very good. Or you're left with find all and grep and hoping that you didn't rename the wrong one or hoping that you caught them all and hoping that your test suite is exhaustive enough. If you have an application or a library that is actually exhaustively covered with types, the downside to what I mentioned earlier that it's gradual and you can layer it in as you go is you only have to layer it in as much as you want to, which means you can end up with a type system or a type coverage level that doesn't actually let you
Starting point is 00:22:40 get some of these benefits. But if you do have it fully and exhaustively checked, and you don't use... I should come back to this in a minute. You don't use TypeScript's escape hatch called Any. If you're not using those things, then TypeScript can actually exhaustively tell you, hey, here's everywhere this is being used, and you need to change it. And so you can do the thing that you do in more thoroughly type checked languages traditionally of making a change and then just following the compiler errors or doing a refactoring that can actually exhaustively know where all of the refactor points are rather than that heuristical model or that grep and hope model and trust your test suite. I mentioned TypeScript's any.
Starting point is 00:23:21 I should elaborate on that. One of the places where TypeScript leaves some unsoundness on the table is it has a type called any, which if you have a type that is any, it can be assigned to anything and anything can be assigned to it. And this is an escape hatch. Sometimes you're just in a spot where you're saying, I have no idea what this is, or I don't have time to write the types for that corner of the ecosystem, which leads me to another small tangent, which is to say TypeScript also gives you the ability to write type definitions for third-party code. So you can create a description of what the types are for some library that you're interacting with. So I'll come back to that in a minute as well.
Starting point is 00:23:59 But this AnyType, anywhere that you're using it, it's basically like, yeah, this is just JavaScript, man. Do what you want. I'm not going to try to check anything anymore. And that's very powerful. But unfortunately, it also just means that anywhere you use it, you're not getting any benefits. And any type checking that happens to intersect with it, TypeScript's going to like, nah, man, you said any. So anything goes here and you lose that. So in TypeScript 3, they introduced a different type called unknown, which is actually much more useful for the way I write JavaScript. And unknown is a type that says, if you want to do anything with this, you have to check what
Starting point is 00:24:36 the type is. And that leads to the fact that TypeScript's type system is actually very sophisticated and does flow analysis. So if you say I have an input to my function and I can define that input as being an anonymous union type, or I can say this is a string or a number, it's valid for you to pass me either of those as the argument to this function. Then within it, you can write if type of this argument equals number within that if block, it now knows that it's a number and it's legitimate to add it to other numbers and to divide by it and to do other things you would do with numbers. And then you can put an else block and it'll know that, well, you checked in the if block if it was a number. So this else block, it must be a string. And here you can call methods
Starting point is 00:25:21 that exist on strings to it, like to lowercase or to uppercase or whatever else. And it won't let you do that in the number block. Well, if you take that and include the idea of this unknown type where unknown, unlike any, won't let you assign it to anything that is well typed. So if you say, let X be a number, and then you have Y, which is unknown, and you try to assign Y to X, TypeScript will say, no, that's out of bounds. You haven't actually checked that this thing Y is a number. You can't assign that to X. So similarly, you can use this kind of narrowing notion, which is what TypeScript calls it, because you have some set of possibilities,
Starting point is 00:25:58 and you're narrowing the set of possibilities. In the example I gave a moment ago from string and number to just number or just string. Similarly, unknown says the set of possibilities. In the example I gave a moment ago from string and number to just number or just string. Similarly, unknown says the set of possibilities is unbounded. I have no idea what this could be, which sounds like any, but the difference is here, TypeScript checks you. It says, no, you have to check. So if I have a function which takes in some argument, which is unknown, and I say, if the type of this argument is a number, well, TypeScript now narrows it. And it says in that block, hey, this is a number, you can do number things with it, but you have to do that. And so unknown lets you deal with things like, hey, I got this blob of
Starting point is 00:26:35 data from across the internet. I have no idea what it is. I mean, in principle, it might be what my API promised, but in principle, it might just be a bunch of binary garbage, or it might be a JSON object that looks nothing like what my API promised or whatever else. And so unknown gives you this tool for describing that in a more robust way. Again, this is part of that trajectory I described of TypeScript saying, how can we capture this thing that's really useful, which we used to do in this more loosey goosey way, and give you a way to express it with much more strict and sound guarantees. So today, if I'm converting a code base, there's an ES lint rule, which is a JavaScript linter that integrates with TypeScript, where you can just say never allow any. And if I were converting a TypeScript or code base to TypeScript today,
Starting point is 00:27:20 I would turn that on and say, it's legitimate for you to use unknown, because then you'll have to check it, you'll have to do whatever runtime checking. And sometimes you do have data that you don't trust or types that you don't trust coming in from the outside, but then you're going to be safe when you're using it. So one thing that you mentioned that I'm not clear on is like gradual types versus type inference. So if I go back to your example, we take a JavaScript file, we rename it dot TS. But so at that point, it has no type annotation. So correct. What are the types then? Are they any? Some of them will be and some of them it will infer. So if you write let x equals
Starting point is 00:27:58 42, it's going to infer that x is a number. And if you say return X there from a function, it will infer that the return type of the function is also a number. Now, if you have some conditional block and you return 42 from one of them and the string hello world from the other, it'll happily just infer that the return type from this could be a string or a number.
Starting point is 00:28:21 Cool. And occasionally that's what you want, but a lot of times it's not. So often good practice is to then start adding annotations and say, no, really, this function should only return a number. Please give me a typer if I return a string. The things that will default to always making any are arguments to functions because it does not do the kind of flow analysis and type checking analysis that some languages in the standard ML tree of languages will do where it'll say, hey, I can see from how this is used that this argument
Starting point is 00:28:52 must be a number. It won't do that. So it will infer return types and assignments, but it won't return function arguments. It also won't infer items declared in the body of a class. So if you say class person and then declare a property in it name, but you don't give the name a type, which is a valid thing to write in JavaScript, just name with a semicolon after it to say, hey, there's a name property on this object. TypeScript will treat that as any as well. And so at that point, then you can start layering in and adding in types where needful to say, hey, no, this function doesn't actually accept anything. And there is a flag in the compiler called no implicit any, which is part of that strictness checking,
Starting point is 00:29:35 which will say, hey, if you convert it a file from dot JS to dot TS, I'm going to give you an error all the places where I could infer any and I'm going to say no you actually have to fill those in with a type so mostly function arguments or class properties like that so that's the gradual typing side you can add in types progressively but then the other side of it is you might want to represent types that exist outside your library for an untyped JavaScript code you're using. So for example, Lodash is a very common utility library that many, many JavaScript developers reach for. It's not written in TypeScript, and it doesn't ship any types of its own as a result. But there's a repository called Definitely Typed, which Microsoft maintains, where there are third party community definitions,
Starting point is 00:30:30 where you can just write out a function signature that says underscore dot map, which is the low dash and underscore there is a function and it has this type signature and it doesn't have any body. So I'm just giving it a declaration. But I can say underscore dot map takes in an array and a function to operate over that array. And the function has to have the same type signature to work legitimately with this. It understands generic types and things like that. So you can write very sophisticated expressions that way. And now when I interact with Lodash, I can also install the types from this library. I can install them as at type slash Lodash as my package name for them.
Starting point is 00:31:06 And I'll just be able to say, hey, I actually get when I import and use underscore dot map, I get type annotations for it. So if I misuse it, I'll get that feedback from the compiler, and I'll get autocomplete from the language server and all of those things. So you have this simultaneous ability to do type inference, which means there's a lot of stuff you don't have to write. A lot of good TypeScript code, especially in apps, tends to look a lot like the JavaScript code with little sprinklings of annotations. Like I said, kind of at API boundaries is probably the best way to describe it at functions or class signatures, and otherwise very similar to what you would already be writing.
Starting point is 00:31:45 In the body of a function, you're rarely going to write any type signatures because it does have good enough inference for that. I mentioned earlier, I work with Ember.js and TypeScript a lot, and we maintain these open source community definitions for Ember because Ember itself is largely written in TypeScript at this point. But I mentioned earlier semantic versioning and TypeScript not doing it. Ember.js is probably the most semantic versioning thing in the entire world. It's very strict about backwards compatibility. So we've yet to define a good story there between the two, because we really don't want it to be, yeah, Ember ships its types now. And oh, you just upgraded from Ember 3.12
Starting point is 00:32:25 to 3.13 and your build broke because the TypeScript version that we shipped broke or our type definitions broke. That wouldn't affect anything at runtime because it all gets stripped out, but it's still a really bad experience for consumers of Ember. And since TypeScript 3.5 might break versus 3.4 in some small ways. We really appreciate that they're doing that work because otherwise our lives would be much less pleasant in that space. They're trying. They are trying. You mentioned earlier something that surprised me.
Starting point is 00:32:53 So my understanding is right, like TypeScript exists at compile time and then at execution time, it's JavaScript. But you mentioned looking at a type. So if the type is X, then do Y. So how does that work? Because I assume at runtime, you just have JavaScript types. smart enough to understand that at time A, the type is string or number. But at point B in your code, you've done this runtime checking. You had on someone who talked about refinement types in the past. And I think you've talked to someone who had dependent types. And both of those can do some of these kinds of things, expressing this idea of runtime behavior that has to be validated by the actual checks you do in order to type check to some extent. And TypeScript isn't
Starting point is 00:33:51 doing either of those exactly. But through this runtime analysis, and also through some other sophisticated things you can express with the type system where you can return different types conditional based on the inputs to the function. TypeScript is the closest thing to dependently typed and refinement type systems that actually is in production at scale anywhere. It's not doing those things, but it's probably the biggest step in their direction that you're seeing in sort of industry use on a wide scale. And so it's using that notion of I'm going to, and again, this is not the same thing as refinement types in Liquid Haskell. So please
Starting point is 00:34:30 don't email me, dear listeners. I know it's not that, but there's an analogy here where it's taking the type and refining it using that runtime flow analysis. And it can do the same thing with switches, switch statement where you have a set of cases within it and stuff like that. So you can actually emulate exhaustive pattern matching against a tagged union. You have to do the work of building up the tagged union yourself because JavaScript doesn't have those. And then you have to add in some machinery to say, assert that this thing will be never in the default slot. Never is a type that if TypeScript sees that your runtime code ever actually hits it, it says, hey, this is a type error. Again, through that kind of dynamic analysis of that flow down through your code. So very sophisticated, very capable, so much so that in fact, even when I'm
Starting point is 00:35:17 working in stricter languages like Elm or Rust, sometimes I miss some of those incredibly rich, very dynamic capabilities that come out of TypeScript as a result. Yeah, it seems very flexible. And I can see the connection to the refinement types because you're saying, you know, TypeScript is type annotations. You know, in refinement types, kind of, at least Liquid Haskell lives in these like kind of comments, right? Where you'd say like, hey, this int has to be greater than zero. You know, if TypeScript were like, if you did like slash slash colon int, right? Where you'd say like, hey, this int has to be greater than zero. You know, if TypeScript were like, if you did like slash slash colon int, right? If you put all the types in as comments, it would be kind of similar, right?
Starting point is 00:35:53 It's a similar space. Yeah. It's this extra layer on top of what the regular story for the language is there. And it's almost like, I mean, it seems to overlap with linting a bit too. Like is TypeScript a language? Is it a really fancy linter? Right. That is an active debate in some of the communities I participate in. And actually, as one of the maintainers of this Ember TypeScript integration, I make very clear to people that here are what my preferences are. But at the end of the day, if you just want to use it as a really fancy linter, rather than doing what I described, borrowing the term from Edwin Brady, who is the author of Idris and so on, this idea of type-driven development, where as much as possible, I'm using the types to guide how I build. And I end up using a combination of types and tests, which can be
Starting point is 00:36:40 very, very powerful as a software, kind of one-two punch in engineering to get rigor on both the runtime and the design space, both of them eliminating different classes of errors. Well, look, at the end of the day, if you just want to write some pretty loose, like loose Java style JavaScript, we're going to enable you to do that. But over here is the happy path. Do it this way, man, is kind of my verbal strategy in those conversations, as it were. Yeah. And maybe you can gradually approach it. Right.
Starting point is 00:37:14 Put it in your build pipeline as like a linter and then you slowly. Yeah. And I think that's one of the reasons that TypeScript has been successful, because people can use it that way and then say, oh, I also learned this thing from reading a little bit about Rust the other day. I wonder if I could do something like that over here. Oh, I can. Cool. And that ability to gradually level up in your understanding of how to use types is very powerful, I think. It doesn't feel like jumping into the deep end for a new JavaScript developer the way that jumping into something like Elm or Rust can.
Starting point is 00:37:50 So you have done some sort of training on TypeScript, and I was looking through kind of your notes, and I found this quote, maybe you could explain. It says, types are just shapes, exclamation. Maybe I need to say it with emphasis. Types are shapes. Types are just shapes. Yeah. So this is one of the other really interesting defining features of TypeScript. Most type systems that most people are used to, including most notably in today's space, Java, C Sharp, and C++, and for the most part, Swift, with an important qualification around protocols. Certainly also Rust, Haskell, almost all of these have what we would call a nominal typing system. And the idea there is that types are identified by their names. So if I have class person,
Starting point is 00:38:34 which has a name, which is a string on it, and then I have class human, which is a class, which has a name, which is a string on it, those two are not substitutable for each other in any of the languages I just mentioned. In TypeScript, they are. Because TypeScript looks at those and says, oh, that's a shape. And that shape is an object with a property name that is a string on it. And the vast majority of the time in dealing with JavaScript, that is exactly what you want. Because JavaScript is just dealing with objects as these blobs of data. And you might use the name as a signal to other developers. But for the most part, and this is a place where writing in TypeScript actually feels much closer to writing in a dynamic programming language, a dynamically typed programming language,
Starting point is 00:39:22 than most others. It sounds like duct typing. It sounds just like duct typing. Yeah. It's like duct typing that gets checked for you. You say, hey, this function needs a thing, which is an object, which has a name on it, and it's a string. And TypeScript says, cool. Well, I have all of these objects in my system, which have that. And some of them also have an age on it. And some of them also have this walk method on them. But all of them are totally compatible with that because they match that shape. And because they match that shape, they're good to go. And so a lot of especially functional programming idioms, which often you really just want to say, hey, I only care about this one aspect of this. And if you give me something with that aspect,
Starting point is 00:40:06 I can do something with it and then hand you back that thing transformed in some way. TypeScript lets you do just that. It lets you say, hey, you hand me in an object with a name on it, and I'll hand you back the length of that name. And I don't care how rich or sophisticated the rest of that object is. I don't have to know anything about the details or the internals of that object. As long as you can't be an object that, among other things, included a name that was a string, we're good to go. And that idea we call structural typing, all you care about is the structure of the thing you're dealing with. A couple other languages do have this. Swift's protocols are structural in nature, which is very different for me.
Starting point is 00:40:46 I've been digging into Swift over the last month or so, a bunch, having spent the last almost four years playing almost entirely with Rust in my spare time. And Swift's protocols and Rust's traits look very similar. There's this way to describe a behavior that something can conform to, like an interface in Java or C Sharp,
Starting point is 00:41:04 but which you can apply to something after the time of definition an interface in Java or C Sharp, but which you can apply to something after the time of definition. So in Java or C Sharp, you have to say class foo implements interface bar. In both Rust and Swift, you can say this type implements this trade or protocol, whether Rust or Swift, well apart from the definition, which is very powerful. In Rust, you have to include the body of whatever it is you're implementing. You have to define that there. Swift is perfectly happy to say, oh, you already have the relevant properties and methods. Cool. You're good. So you can have bodiless implementations. Also, Elm has this notion of structural record types, where again, I don't care if your type is a
Starting point is 00:41:45 superset of this. As long as you hand me that, you're good to go. And I believe OCaml's notion of row polymorphism fits into the same thing. But don't quote me on that because I haven't done much OCaml. It's funny because I had an episode about PureScript, which I believe it also has row polymorphism as one of its unique features. And I think it has something to do with JavaScript, where if you're compiling something down to JavaScript, you're like, I really want this. That's a good insight. And I hadn't thought of it before,
Starting point is 00:42:11 but I think that's exactly right. I will also say that by and large, a lot of the flame wars between dynamic and static typing seem to me to be fairly well dissolved by this. Not all of them. You have some zealots on both sides who are like, well, we live in a universe where things are not actually perfectly computable. And so types are a lie and they're always a lie. And you have people on the other side who say stupid things like, if you're not using types, you're being unethical and irresponsible. And I
Starting point is 00:42:40 think both of those are really stupid things to say. And they're just, frankly, they're intellectually folly. Because it is true that you can't cover everything perfectly with types on that side. But you also can't do that with tests. And most of the people who say that really like tests, on the other hand, quite legitimate to say, look, for my use case here, I want maximum flexibility. And I'm willing to take the trade-off that comes with that of losing some of the things I might get out of types. So a couple of friends of mine will make exactly that argument. And we have friendly back and forths about whether untyped or structurally typed is good, or these nominally typed languages over here are good. And most of them would frankly admit that if you're writing low-level system software that's a TLS implementation
Starting point is 00:43:25 or something, actually having Rust in its types is probably really high value. Whereas in other systems, certain kinds of web systems where you're just doing really loose flowing data transfer, something like Clojure or Elixir or Erlang, which doesn't have those, might actually be more productive for you in certain ways. And so I think smart people recognize that there are trade-offs with these. TypeScript and other things which embrace structural typing as at least one tool in the toolbox seem to me to somewhat bend that curve and make it easier for you to say, I'm mostly going to write this like it's structurally typed, just sprinkle in some annotations on top and really be good to
Starting point is 00:44:06 go. And in the case of something like Elm, you're getting that with Henley Milner style type analysis. So you're also getting this exhaustive whole program type checking with perfect inference. And of course, you're going to add some annotations in general because they're handy for other humans. But in my experience, structural typing really is this incredibly sweet spot where it kind of feels like duct typed dynamically programming, but you're getting all this help of the compiler saying, hey, this could be null. And you might want to check that here before you just call the function so that you don't end up with Bugsnag or Raygun or whatever saying, hey, undefined is not a function. You just had four
Starting point is 00:44:44 users who couldn't place orders because your function wasn't defined here. No, not that I have deep and painful experience with this or anything. That's funny. Yeah. I remember I had an episode with Jim Blandy talking about Rust. And I remember his big complaint was like, there's a million line JavaScript code base out there. And if you make a typo, then you just have to wait for somebody to hit that line and execute it. Yeah. It really stinks. And sometimes the way that you get to those combinations is just incredibly arcane. There was a bug I dealt with in my previous role where we knew the bug existed for two years and we could not reproduce it. We could never figure out the set of steps that users were going through to hit that flow. And so we would see it show up with a stack trace in Raygun. And we would look at it and we would say, we would trace through every part of our code flow. And we would just say, oh, hey, this thing just happened. We were like, you found it. But it was a case of something ended up being possibly undefined.
Starting point is 00:45:48 And even when we had written the TypeScript, TypeScript has a couple of these little escape patches. And one of them is you can write an exclamation point to say this thing will always be defined. And we actually had a nice little comment on this block of code that says, here's why this will always be defined. Spoilers, the comment was wrong. The compiler was correct. Now, the problem wasn't that spot. The comment was actually correct in the small, but in the large, the system was wrong. And it took two years. And finally, our product manager just happened to be poking around one day and found the right combo that triggered it. We fixed it and it went away and it was a good feeling. But that example
Starting point is 00:46:25 was one when I listened to that episode that I resonated with very, very deeply. I was going, yes, Jim, that's exactly it. Yeah, that is a crazy story. Yeah. Whenever you can get something out of comments and have it checked somehow. I remember years ago working on this old code base and finding this method that I needed to interact with. I had this giant comment that said like, you know, this thing takes the following like seven arguments and this one should be this and this one should be that. And then looking at the method and it only took three arguments and they weren't the same. Oh no, oh no. And I think that's one of the places where TypeScript finds a niche is a lot of places, especially if you're writing large scale applications,
Starting point is 00:47:03 they're writing these big JavaScript doc comments that are annotating the parameters for the types already. And so you actually end up with briefer, smaller amounts of code by adding the type annotations in place of these JS dot comments. And then the compiler can check it for you. TypeScript also has a superpower where it'll check your JS dot comments, which is really cool. It'll say, oh, hey, this is a valid block of JS doc. And you've described this parameter as being a string. So now I'll actually check that if you use that pragma that I described earlier, where you can say TS check, which is really nice. Yeah, that's crazy. So Rust versus TypeScript, which is better? Oh, man. So you remember how a minute ago I was saying that people say dumb
Starting point is 00:47:46 things on these type four arguments? For that reason, I just refused to answer the question as stated because I think any answer I could give would end up being a dumb answer. I like Rust better on a day-to-day using it level. For the last couple of months, I've been working on a project called Volta, which we built out here at LinkedIn, but it's an open source project. It's a node version manager tool chain, which gives you nice reproducible environments so that you can make sure that all the developers in your team are using the same version of node and the same version of Yarn or NPM and the same stack for any CLI tools they're using or things like that. And we wrote it in Rust in part because the original author behind it, Dave Herman, helped drive Rust at Mozilla. And he's fantastic. If you ever get a chance to talk to him,
Starting point is 00:48:35 I look up to Dave a ton. But we've been using Rust. And so I went from my previous role where I was writing TypeScript all day every day to my current role where I'm doing a bit of TypeScript, but mostly writing Rust every day. And that soundness and exhaustiveness of it is just wonderful. And a lot of the built-in language constructs that you end up having to build yourself in TypeScript, things like rich enumerated types that Rust has, where you can say, not just this is A or B or C, but A or B or C can themselves be rich data, not just an integer. So A can be A with a string wrapped inside it, and B can basically be a struct definition, which has all these fields on it and so on. You can build up those kinds of abstractions and check against them in TypeScript, but you have to do all the work yourself. And the language just guides you through that with Rust automatically and right out of the gate.
Starting point is 00:49:28 And it is deeply joyful to me. But I also have to admit that because of weird things about my background, Rust just scratches an itch that's just right. Because the first two-thirds-ish of my career up to this point, I was writing C and C++ and sometimes Fortran. And so I've spent so much time in that kind of low-level world that Rust does this magic trick where I'm still writing that kind of extremely high-performance, memory-controlled, low-level stuff. And I'm also getting all these niceties of a high-level language. And so I like that enormously. And the net of it is that Rust just feels better to me. But I can't say that either of them is a better language. I think it's more accurate to say that both of them are very carefully,
Starting point is 00:50:17 thoughtfully designed languages that are targeting very different worlds and very different spaces and doing so very effectively. Rust has this goal of zero cost abstractions and being able to be as fast and sometimes amazingly faster than C or C++ and safe at the same time. And it's doing that incredibly well. And there is a cost to it. I think the cost is a lot lower than some people sell it as being, but there is a cost to it. You have to think about things that you just don't have to think about when you're writing C-sharp or JavaScript or any Python or anything like this. And by the same token, it's not trying to be what TypeScript is trying to be. TypeScript is, as you summarized it earlier, trying very hard to meet JavaScript developers where they are and enable them to, whether it's by way of a fancy linter or because they actually just really are in love with Elm or PureScript or something, but for good reasons or
Starting point is 00:51:16 bad, can't write it in their job. And a lot of times it's good reasons. I mean, I love Elm, but it was a running joke at my previous gig that I loved Elm and I would never pitch it because it just didn't make sense for us in that context. And TypeScript made fabulous sense. So whatever end of that spectrum you're on, TypeScript is meeting you there and enabling you to do those things. And it just really doesn't have to try to worry about memory management because it's not shooting for that space. It's funny. It makes sense that you mentioned that you had kind of a C background because in my mind, I was thinking,
Starting point is 00:51:48 it is strange for somebody to be interested in both like Ember and Rust. Like that seems like a very, those circles don't intersect. Yeah. So like wrapping up on TypeScript, when should people not use TypeScript? That's a great question.
Starting point is 00:52:02 And I think there are a couple places where I would say don't. One is if you just try it and try it legitimately, not just this is new to me, and I hate it, but legitimately go for it for a while. And it just doesn't pattern match right in your brain, for lack of a better word. I have, I mentioned earlier, a number of friends for whom even with structural typing systems, as often as they try to use them, they just bounce off. These are people who know Haskell. They're people who are really good, really top of their game engineers, and it just doesn't work.
Starting point is 00:52:36 At the end of the day, like I said, I think the using types is an ethical constraint thing is just dumb. The best programming languages research we have says you do find certain classes of bugs with types. That's great. It's helpful. But those kinds of things are limited enough that we just don't really have any grounds for those kinds of sweeping claims. And so if you and or your team bounce off of it, I think that's okay. I think in certain cases, people's brains just work differently. And I think that really is okay. My brain works in types. I've been trying to shove things like pattern matching and those kind of rich data types into C since before I knew they existed
Starting point is 00:53:18 in other languages. I was trying to make this kind of thing work with enums and unions and whatnot. Clearly, my brain just runs that way. I want to write these kinds of constraints. And other people don't. And that legitimately is okay. If you have a team that is just hostile to it, don't try to force it. It's not worth whatever gains you might get out of it. I would also say that in certain sufficiently large code bases, if you don't have a lot of will, it might not be worth it because you really do have to have the will to see the conversion through and it's going to be long. It's going to be an enormous amount of human hours and effort. Now I say this as someone who's been working on planning out how to do this on an app that has
Starting point is 00:54:03 over a million lines of JavaScript in it. So glutton for punishment, I don't know, something that way. But there are situations where it may just not be worth the investment to you and your organization. And I think that's also legitimate because these are engineering trade-offs. They're not things where we can just snap our fingers and have the code base magically all typed. If that were the case, I would say that almost everybody, unless you just can't do types, and even then, have you tried a system that has structural types? You might try it. It might be different. But with that exception, if we could all just snap our fingers and have fully typed TypeScript things, I'd say just do it.
Starting point is 00:54:40 But most of us can't. And there's an engineering tradeoff there. And it may not be worth it. It may not be worth whatever velocity it costs you in the meantime. I think it'll probably pay for itself in the long term. But I also think that gets at the other place. If you're really just whipping up something that you intend to throw away, and you really intend to throw it away, just do it in JavaScript if you're comfortable with that and you don't
Starting point is 00:55:01 care. For me, I'm actually faster building those kinds of things with types. And I've also experienced that painful thing where you say, I'm just going to build this little thing to wrap around and execute this as sort of my own mini test configuration that nobody else will ever use, surely. So it doesn't matter if it's really well factored. It just has to be a little script that I can get the job done with. And then soon everybody in the organization is using that script. Things have a tendency to grow a life of their own. So you should probably be more skeptical of the idea that you're really going to have a one-off throwaway script. But those kinds of things, like I said, for me, I mean, I write some of those in Rust at this point. Call me crazy,
Starting point is 00:55:37 but I just, I like the feedback cycle. I get there and I enjoy using it and it works well for me. So obviously I don't mind using types even for throwaway one-off scripts, but that would be a place where people might not find the value trade-off high enough. I just read an article that mentioned something about proof of concepts. And I agree with the sentiment where it's like everything that's running in production was somebody's like throwaway proof of concept, right? They were like, there's like the great vision that you want to build and you never get to. And the proof of concept that still lives on, right? Those are the two.
Starting point is 00:56:06 Yep. And some of them are real nightmares, but they're still going. And it turns out that code that's actually doing something is really valuable. Delivering value, right? So when I started this podcast, one of my ideas was sort of to get down kind of in the weeds of coding, like an audio format. Turns out that that's like super hard. So I don't know if I've given up on that. But like your podcast, you actually have like code samples and walk through them.
Starting point is 00:56:33 Where did you come up with this style and structure? I wish I had a good answer for that. Mostly, I think it was that I was too ignorant of how incredibly hard it would be when I started. And I thought, surely one can do this, right? Maybe the reason no one has ever done this that's come across my radar is I've just missed it. As far as I can tell, no. People just recognize that this is really hard and you shouldn't do it. I ended up starting Neurostation when I did in part to help myself keep learning. And then I found that teaching as that podcast was designed to do
Starting point is 00:57:06 without actually talking code sometimes is really difficult. Sometimes you can get away with talking conceptually, but when you're trying to teach something like a programming language, you really do just have to talk code sometimes because it's a programming language. So what I ended up doing over the life of the show was figuring out how to boil down the examples to really, really minimal things that you could actually maybe say out loud, and maybe listeners could parse out loud. And then if they didn't, only have to re-listen to it once to catch the parts that they missed. There was also an art I discovered over time of figuring out how you pronounce those strings of characters. A function named foo, taking the arguments bar and baz of type string
Starting point is 00:57:54 and number and returning a new struct with these fields or something like that. Over time, learning how to actually say it, because I was talking Rust and saying FN, foo, open parentheses, which I did do in a couple episodes. And it turns out you just can't parse that because you're trying to translate from audio into a visual representation of that. Whereas if you just think about what the actual semantics are that that syntax maps to, you can communicate that. You can say, here's a function named foo, which takes bar being a string and baz being a number and returns a new structure, which has some embedded field in it. I can say that and you can understand it.
Starting point is 00:58:36 Because at some level, when we read syntax, that's what our brains are actually doing. We're not thinking fun when we see FN for function. We're thinking, I'm seeing a function definition. And we get very accustomed to parsing those details and translating them into the semantics they mean, at least at a high enough level when we're reading through code. So the trick for me was finding a way to figure out how can I do that parsing kind of ahead of time, do the pre-parsing to turn it instead of into some bytecode or something, some AST, to turn it into something more like a syntax tree for English, which is what we call a sentence in English. But to kind of do that mapping into what are
Starting point is 00:59:22 the actual semantics that we're thinking about. whether I would recommend it to anybody else. Well, I don't know. It was, it was really hard. A lot of times I would end up leaving myself notes in the script of how to pronounce a given definition or how to read a particular thing, because otherwise I would get to it while recording and just say, Oh no, Oh no. And I would try it three times and have a whole bunch of editing to do to try to clean it up into something that was actually useful. Yeah. I think it's super tricky, but I think it's great that you made an effort at it. Maybe we'll get better. Like maybe my rust is super rusty, if that makes any sense. Like I know almost no rust besides talking to people, but I have explained to people my challenges with
Starting point is 01:00:01 the language by saying like, if you have a variable X equals one, and then like Y equals X, and then you print X, right? Move. Yep. Yes. That one sure confuses people at first. So the punchline there is that will not compile. And that may be confusing for you if you haven't worked with Rust before. Though I think the specific example you just gave may compile because integers implement
Starting point is 01:00:24 copy. So by default, the compiler will just copy that for you rather than cloning it. But if you did it with an own string, it would behave exactly the way you just described. So if you said let x equals string from hello world, let y equals x, print x, boom, this doesn't compile. You moved to y and you're going to say, what? What do you mean? What? I've never seen anything like this. Yeah. See, this is why I don't do ad hoc reading a code in an interview. So I pulled this bio up of you. It says, Chris is a husband and a dad, a theologian, a composer, a poet, an essayist, a software developer, a runner, triathlete, podcaster, and all-around nerd. What's your secret? It sounds like you maybe consume a lot of amphetamines. Happily, no. I have a couple things going for me that way. One is that most nights, I only need seven to seven and a half hours of sleep. And I'm not
Starting point is 01:01:17 one of those people that lies to myself about how much sleep I need. So I went through a pretty bad season of burnout last year for a lot of complicated reasons, including things like moving across the country after getting a master's degree and my dad having cancer, brain cancer, which he came through well, he's doing really well. But that plus job stuff, it just, I got burnout. And those days I was sleeping nine, nine and a half hours a night. So I listened to my body very well. That is actually also part of it. I listened to my body well, but I only need seven to seven and a half hours of sleep a night. And that extra time matters. I work from home and don't have a commute. And for a lot of people, that's anywhere between one
Starting point is 01:01:54 and three hours a day. If you're riding a train, maybe you can get some of that back. But if you're driving a car to get through LA somewhere, I mean, good luck. Maybe you're listening to an audiobook at best. So one thing I just always have to say to people when they ask this is I have a lot of extra time. That adds up over the course of a year. Figure somebody takes four to six weeks off or whatever, you're still talking about 800, 900, 1000 hours of time. So that makes an enormous difference. And it's actually one reason why I'm really, really bullish, I think is the right one on remote work and people being
Starting point is 01:02:31 able to work from home and not just in our industry, but wherever we can enable those kinds of things. I also get to spend way more time with my wife and my daughters. And that's massively important. I mean, I got to see them at lunch, I went upstairs and made lunch for all of us and those kinds of things. So for those reasons, I don't work 10-hour days, but I block out that somewhere in there, depending on the weather, whatever time of day is best. I live in Colorado. So whatever time of day is best varies enormously. I'll be getting out for a run or something like that. And I just know that there's going to be a couple hours in the middle of the day where I stop and run and I go come back, take a shower, eat food,
Starting point is 01:03:26 et cetera. And then I hang out with my family in the evening. And then there's time after my kids go to bed where some nights I'm just hanging out with my wife, but some nights I'm writing podcast episodes or editing podcast episodes or whatever the case may be, working on reading some nerdy theology book, so on and so forth. So it's mostly just having a good sense of the rhythms of my day and sticking to those. And then like I said, all that extra time that I get out of not having a commute and needing less sleep. Yeah, I think it's harder than you're making it sound. So I work from home too. The listeners can't see, but there's a chair behind me there. And I think that I have
Starting point is 01:04:01 dedicated some of the time you use for podcasting for sitting in that chair and playing Angry Birds on my phone. I also got rid of Twitter recently. And I've been really aggressive about removing things like social media. And that actually helps a ton too. But I mean, I waste time sometimes. I also... This is huge. So I take a weekly day of rest. And counterintuitively to a lot of people, I think that's actually extremely helpful in this. So for over a decade now, Sundays, that's the day I pick because that's when I'm going to church, it's time I spend with family, etc. I don't work on these things. Sometimes I'll muck around with... This Sunday, I spent a little time mucking around with my
Starting point is 01:04:41 website, which I'm in the middle of redesigning. But I did that because it felt restful. And you read part of that bio, it included theologian. I'm a Christian. And I actually, I look at this idea of Sabbath from the Old Testament, the Hebrew Bible. And it just seems deeply wise to me. People sometimes get hung up on it as this kind of binding rule. I actually just look at it very much as a gift. Humans need rest. And especially in our industry, it can be this weird badge of honor to just say, no, I go all the time and I do stuff every day and I work 14 hour days. And that's nonsense for one thing. You're not working good 14 hour days, seven days a week. I just like to be effective with the time and the abilities I have, such as they are, and with my absurd drive to always be writing a blog post. So I try to use
Starting point is 01:05:31 that well. I figure if I have it, I might as well bless others and encourage and help others with it. But I also have to remind the people around me that just because I'm like this doesn't mean it's more valuable or more worthwhile. It stresses the heck out of a lot of people I know and love to think about trying to do all the things I do. And I say, no, it's okay. I just really like doing things and I'm good at doing things. You don't have to be as interested in doing things as I am. It's okay to spend more of your time proportional to me reading novels. I spend a couple nights a week usually doing things that include things like reading novels or playing Mass Effect with my wife and then recording a podcast about it because we're nerds and that's what we do. Check out MassEffection.com if you want to hear that.
Starting point is 01:06:13 It's nerdy and hilarious because it's basically us ranting about a video game and flirting. But I do these things because I love them and I enjoy them and they seem to be an effective use of the way I'm wired and built, but I don't feel the need to define myself in terms of them or find my worth in doing them. So much of our sense of fatigue comes out of this notion of deep obligation that comes out of that sense of measuring ourselves and our worth out of our productivity, rather than these being things that we can do freely and enjoy. In my view, because we're made to be creative in the image of a God who is creative and made a pretty spectacularly crazy, weird world out there as I look out my window right here. It's a wacky place.
Starting point is 01:06:56 Have you noticed? It's wild. And so my worth doesn't hang on that. So it really is okay. Well, that's a very healthy attitude. And I have to think that some of your success relates to that. Like the fact that you explored rust, not as an obligation, but as a joyful endeavor or whatever you want to call it. Yeah. I think that's right. Well, I think we went through all my questions, Chris. Where should people find you online if they want to learn more about you? As I mentioned, no longer on Twitter. The only thing you'll find on my Twitter account is a link to all these other places. My website is the main place, chriscrycher.com. I blog a lot there, as I mentioned. You'll find updates there multiple times a month, sometimes
Starting point is 01:07:35 multiple times a week, rarely multiple times a day. I try not to do that because it usually means I'm not doing something else I should, but occasionally let myself get away with it. I also have a couple newsletters, one at button down dot email slash Chris Kreicho, where I'm doing some long term thinking out loud about questions around culture and late modern individualist liberalism and kind of these big structures societally. And a lot of cases, just trying to funnel people toward people much smarter than me and much better read than me who are saying interesting things about them that I think are worth engaging with. Sometimes that I disagree with, but that I think are worth engaging and thinking well on. I also have a newsletter for a side project I'm working on at button.email slash rewrite, where I'm trying to build the world's best research writing application, which is probably the most absurdly ambitious thing I've ever done in my life. And I have no idea whether it'll succeed, but hey, it'll be fun while I try.
Starting point is 01:08:35 And perhaps most interestingly, and related to some of these notes, we've just kind of touched on, I have another podcast called Winning Slowly, which you can find at winningslowly.org, where a friend of mine who's a professor at Arizona State University and I try to talk through what it looks like from to talk about literally the entirety of human existence because technology, religion, ethics, and art kind of covers pretty much all of it. But this idea of trying to come at how does it shape us to use a smartphone every day? What are the implications for how we think about community of doing social media? What are ways that we can use or choose not to use social media well? And trying to think on those bigger, more structural levels, trying to rigorously engage those questions. And I think that's pretty much it. Well, that is quite a few things, but I think that they're all very interesting. So thank you so much, Chris. This has been a lot of fun. It's been my pleasure. We ran very long, so hopefully it is not too much for you and your listeners. Thank you so much for your time. That was the interview. I hope you enjoyed it as much as I did. The last episode with
Starting point is 01:09:57 Cory Doctorow sparked some interesting discussion on our Slack channel and on Twitter. And the Bob Nystrom interview about interpreters received a lot of attention as well. I'd like to thank everyone who mentioned the podcast on Twitter or elsewhere. The show went super long, so I don't have time to list everybody's names, but let's do a couple. Egal Tabachnik, Jeff Martins, Sean O'Shea, Colin Fay, Matthew Staff, Duncan Adjaye, Tom Mariato, O Fadi, and everyone else. Thank you. So let me know what you think of this episode. I love to hear from people
Starting point is 01:10:29 who have discovered the podcast and are listening through the back catalog, especially, you know, if you'd like to hear your name or Twitter handle or iTunes name mispronounced on the podcast. Until next time, thank you very much

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.