48 ms·
Tricks I wish I knew when I learned TypeScript
- conaclos 5y agoNote that `Readonly<T>` does not prevent a call to side-effect methods when `T` is not among a predefined set of built-in types. Indeed, it prevents such calls only on predefined types such as arrays, maps, and sets. It could be more "accurate" to use `readonly number[]` instead of `Readonly<Array<number>>` for highlighting the difference.
- BoorishBears 5y agoThat example disappointed me a little. It was an easy catch because I was told there's an issue, but I'm surprised const arrays don't at least have a warning there. Or even default to having readonly-like behavior
- nosianu 5y agoWhich "const" do you mean? The one in front of a variable declaration cannot make the array itself constant. That's because that "const" only refers to that variable itself, which is just a pointer (except for the primitive types). The variable declaration "const" means this variable cannot be changed to point to a different object. It says nothing about the thing it points to and that is how that keyword was designed in this language. It's Javascript (ECMAscript), not Typescript. On the other hand, using Typescript (which only adds type annotations but the actual code is ECMAscript apart from very few small things such as "enums"), you can append "as const" after an array though as type annotation, as in const arr = [1,2,3] as const; // Type error: "Property 'push' does not exist on type 'readonly [1, 2, 3]'" arr.push(5); Which is the same as Readonly<type>. This "as const" annotation can be used for any object, not just for arrays. Of course, it can only guard against known methods of mutating an object, such as direct write access to properties and known mutating function calls for known object types such as the built-in ones (Array, Set, Map, etc., each one needs the definitions for the readonly-version of its type in the Typescript-bundled type library).
- BoorishBears 5y agoThis comment would be a lot shorter if you assumed I meant Typescript in response to a Typescript article... But I digress, the point is in my experience Typescript is very good about catching footguns left around by ECMAScript. So I'm surprised there isn't some sort of catch for this as written in the article maybe behind a config flag, not by rewriting the definition.
- nosianu 5y ago> if you assumed I meant Typescript in response to a Typescript article... You misunderstand TypeScript. They cannot 8and will not) change the "Javascript" in Typescript. "const" is a keyword with a meaning defined by the ECMAscript standard. Typescript IS Javascript. All they do is add type annotations. Only some old non-essential features like namespaces and enums need to be transpiled, and "enums" really is not much and should actually be handled by whatever minifier and bundler/packager you use. Other than that, if you removed the type annotations you are left with 100% ECMAscript. Typescript was meant to be just a type-annotation extension and explicitly made the decision that the code itself would always be stock-standard Javascript. Arguably, it was a bad design decision that now confuses lots of people about the nature of Typescript by bundling type-checking and transpiling to some target (originally for older runtimes that did not understand es2015 or were lacking some feature available in the latest JS runtimes and ECMAscript standard). It is therefore not a surprise at all that Typescript did not make "const" into something else. The basis always is the ECMAscript standard.
- ketzo 5y agoWow, the fact that `as const` has such a meaningful difference from a variable declared as `const` seems... not great. Surely they could have gone with, like, `final` or `immutable` instead..? I'm sure they had their reasons. But seems rough.
- cstrnt 5y agoThat's right. But I wanted to to use `Readonly<T>` because it can also be applied to plain objects while readonly cant
- milliams 5y agoI haven't used typescript much but it's surprising to me that you can pass a `const` value to as an argument which is not `ReadOnly`. Does `const` not really mean anything?
- hajile 5y ago`const` means a constant pointer, but doesn't guarantee that the data it points to will remain constant. In practice, functions, numbers, bigint, symbols, booleans, strings, regex literals, null, and undefined are all immutable. Since you can't change the value, a const to one of these guarantees the value will never be modified. Objects, arrays (actually just objects with a different constructor), maps, sets, TypedArrays (real arrays), etc are different. You can be guaranteed that you will be pointing to the same object instance because there's no way to swap out data at a location in memory like there is in low-level languages (yay GCs). The entries inside the hashmap or array can be modified though. Calling `Object.freeze()` will lock down an array or object with some caveats. Sub-objects will still be modifiable (though you could recursively freeze) and this doesn't work for Map or Set (their properties like get/set/forEach will be frozen, but not the actual data) and it will throw if used on a typed array.
- keawade 5y agoThat’s a JavaScript specific nuance that typescript inherits. ‘const’ declares a variable with an immutable reference, not an immutable value. If you’re referencing a simple literal like a string or a number that’s effectively the same thing but for objects (and arrays under the hood of JavaScript are fancy objects) while the reference to your given object is constant, the properties of that objects are still mutable.
- shadowgovt 5y agoCorrect. This is a thing you can do in JavaScript (and TypeScript) that sometimes trips new people up but is exactly what these keywords mean: const foo = []; foo.push(1,2,3);
- AtNightWeCode 5y agoSame in a lot of programming languages. A common source of errors too. Maybe it is a bit more confusing in JS simply cause people have been taught to make an active choice between var, let and const.
- btbuildem 5y ago"any" is such a cop-out, it's a shame it exists. You can't eat your cake and have it too.
- recursive 5y agoThen turn it off with your compiler options. Typescript never would have gained significant adoption without it. It's essential for gradual conversions from js codebases.
- sibeliuss 5y ago`any` is one of the main reasons why typescript is now so popular. Its a dev-conversion tool. It's amazing for teams that aren't ready to make the full leap. But later migration to strict mode is necessary.
- spicybright 5y agoI'm going to be one of those people, but multiple "=" rendering as a large double line is really ugly.
- bmn__ 5y agoYou don't have to suffer (subjectively) bad typography. Cascading style sheets were designed with the ability to override author styles with user styles, your Web browser has settings for this.
- spicybright 5y agoOf course, I'm not going to muck around with brittle webpages that can't take a webpage just to fix one blog post, though.
- recursive 5y agoI totally agree about ligatures. My user style sheet works pretty flawlessly for everything. * { font-variant-ligatures: none !important; } I cannot comprehend how ligatures ever got popular in programming, particularly in blogs supposedly trying to teach new languages or concepts.
- spoiler 5y agoFor me personally, I found that they help reduce the noise in the code. I also noticed that it makes it a bit easier to "read" the code (not just visually, but "semantically" if that makes sense). As in, I think I have to spend less time "parsing" ≤ than =<, but I don't have a way of really "proving" it. However, I am mildly dyslexic, so that might play a role in it.
- recursive 5y agoThat's all well and good for your personal environment. But I think it's a little crazy for a blog post that's supposed to be teaching things to beginners. "≤" is actually a different string than "<=". I think it's really misleading to render one series of characters as if it were another. For instance, julia actually supports ≤. There are others. On top of that, I don't expect a font to be able to correctly parse code. Sometimes "<=" happens in contexts other than "less than or equal".
- marton78 5y agoKinda off topic from someone whos mother tongue is not English: what happened in the past years that people apparently forgot how the irrealis works in English? Shouldn't this be "Things I wish I had known when I learned TS" as opposed to "Things I wish I knew RIGHT NOW"?
- nosefrog 5y agoAs a native English speaker, I never learned formally about irrealis, so it's not possible for me to have forgotten them :P "Things I wish I had known" and "Things I wish I knew" both sound right to me.
- pavlov 5y agoYou’re not wrong, but language evolves. What’s convenient in the mouth of native speakers today will usually become grammatically correct eventually. It would be neat to title blog posts in mock Elizabethan English though: “Miscellania of Out-Most Significance to the Young Man Who Desireth to Learn the Merveillous Type-Scripte”
- throwaway675309 5y agoEven as a former ESL instructor, I'm rather disdainful of statements such as these, as if language is some "well defined codified construct" as opposed to being a fluid means of communication that continually evolves to meet cultural needs. It's like the word peruse, it traditionally meant "to look over something in great detail", yet you'll find the majority of people use it to mean "to look over some thing in a cursory fashion." So for all intents and purposes, that is the new de facto definition of the word.
- 1penny42cents 5y agoThis is a nitpick; but the first example doesn't make sense once we use ReadOnly, because it doesn't return the copied+sorted array. So in practice the final version of sortNumbers would have no effect afaik.
- genezeta 5y agoThe final version of sortNumbers is: function sortNumbers(array: Readonly<Array<number>>) { return [...array].sort((a, b) => a - b) } And sort sorts in place and then returns the sorted array[0]. So here the newly created [...array] is sorted and then returned by sort and then by the return at the start of that line. [0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- nathias 5y agoEverything that TS does JS libraries do better without the horrible tradeoffs ... sadly MS has invested so much into promoting it that it's now almost a requirement for all software development.
- handrous 5y ago> Everything that TS does JS libraries do better Which ones do you need to do everything TS does? > without the horrible tradeoffs Which tradeoffs are horrible?
- nathias 5y agoFor example if you want prop types you use propTypes. In React TS replaces good error handling for horrible obscure errors and slows down development considerably etc. etc.
- shadowgovt 5y agopropTypes does runtime type checking, which is a different kettle of fish from static type checking. The advantage to static type checking is that it removes the performance cost of runtime type checking where it's unnecessary; the language's rules make it impossible to build some constructs where the wrong types get mashed together. The tradeoff is that you have to code so the wrong types don't get mashed together (which is, arguably, your goal in the first place). You can do everything a statically-typed language does in a non-statically-typed language via best practices, but that's a bit like saying you can do everything a compiled language does in assembly via emulating what the compiler would output. In theory, the compiler is saving you the headache of doing that (but depending on the size of what you're trying to write, sometimes it is simpler to write it in JavaScript and skip the type safety. That code is harder to grow, but not all code grows!).
- nathias 5y agoSo the whole baroque arhitecture is there to 'remove performance costs'? That's an even worse reason to use TS than avoiding prop type bugs.
- DavidMankin 5y agoEffective TypeScript [0] has many more well written and explained tips to know to use TypeScript well. I highly recommend it. [0] https://smile.amazon.com/Effective-TypeScript-Specific-Ways-Improve/dp/1492053740/ https://smile.amazon.com/Effective-TypeScript-Specific-Ways-...
- exdsq 5y agoStill working on this, but might give someone a laugh :) Problem 1 from Project Euler in TypeScripts Types https://github.com/iiTzEddyGG/typing-euler/blob/master/src/problem0001.ts https://github.com/iiTzEddyGG/typing-euler/blob/master/src/p...
- chana_masala 5y agoI am highly interested in type programming lately, exactly the kind of thing you're doing here. Do you have any other resources that inspired you? Here are some of my favorites: https://gist.github.com/hediet/63f4844acf5ac330804801084f87a6d4 https://gist.github.com/hediet/63f4844acf5ac330804801084f87a... https://github.com/codemix/ts-sql https://github.com/codemix/ts-sql https://github.com/jamiebuilds/json-parser-in-typescript-very-bad-idea-please-dont-use/ https://github.com/jamiebuilds/json-parser-in-typescript-ver... https://gist.github.com/acutmore/9d2ce837f019608f26ff54e0b1c23d6e https://gist.github.com/acutmore/9d2ce837f019608f26ff54e0b1c...
- exdsq 5y agoI really like Type Driven Development in Idris but that's a little more serious (it's things you can do in production!). But my all time favourite writing ever is https://aphyr.com/posts/342-typing-the-technical-interview https://aphyr.com/posts/342-typing-the-technical-interview
- Xavdidtheshadow 5y agoOne of my favorites is Josh Goldberg's implementation of Tic-Tac-Toe in the type system: https://blog.joshuakgoldberg.com/type-system-game-engines/ https://blog.joshuakgoldberg.com/type-system-game-engines/
- jjice 5y agoI'm so happy powerful type systems are more popular now. TypeScript bringing a great type system to a language as popular as JS is fantastic. Rust is also a great way to get a great type system while staying in a systems programming and procedural environment. Hell, even python type annotations support union types. I never knew the depth of type systems until the last year when I took a type theory course and a compiler course taught by a man who loved his types. So much power - I can't wait to see the future of type systems.
- dreamer7 5y agoCould you point to any good resources on this topic?
- ebingdom 5y agoThe standard reference, if there is one, is Benjamin Pierce's "Types and Programming Languages" book.
- marginalia_nu 5y agoThe grass does seem tend to appear greener in the other paradigm. Barely typed languages like C made rigorously typed languages like C++ and Java seem appealing. The boilerplatiness of those languages made duck typing seem appealing. Writing anything nontrivial with duck typing made more elaborate type systems seem appealing. Needing a PhD in category theory to produce a side effect will no doubt make some other paradigm seem appealing in the future.
- shepherdjerred 5y agoYou don't need a PhD, you just need the first few chapters of [Category Theory for Programmers](https://github.com/hmemcpy/milewski-ctfp-pdf https://github.com/hmemcpy/milewski-ctfp-pdf) :)
- ebingdom 5y ago> Barely typed languages like C made rigorously typed languages like C++ and Java seem appealing. The boilerplatiness of those languages made duck typing seem appealing. Eh, I consider Java to be barely typed too. If you have a variable of type Foo, the type system doesn't even guarantee that you have a Foo in there (it might be null). The whole point of a type system, in my mind, is to guarantee that I have that Foo! > Writing anything nontrivial with duck typing made more elaborate type systems seem appealing. In my mind, this makes type inference seem appealing, not duck typing (which is not well-defined, but most people associate it with dynamic typing). > Needing a PhD in category theory to produce a side effect will no doubt make some other paradigm seem appealing in the future. This oft-repeated exaggeration needs to stop. Using monads does not require a PhD in category theory. If you can understand Promises in JavaScript, then you can grasp how IO works in Haskell.
- irrational 5y agoDoes Typescript get better? I've been forced to use it for my most recent project, but haven't been given any time to read through the documentation. I've found that I'm spending about 99.9999% of my development time trying to figure out how to get my IDE to not show that their are typescript problem. At this point I hate typescript with the burning fury of a trillion suns. I wonder if this is everyone else's experience? Edit: So I take it from the downvotes that everyone else is a genius and I'm the only one that has had a problem learning TS.
- mbrodersen 5y agoSo you didn’t read the (very easy to read) documentation and then complain that you can’t figure out how to use it? And then you wonder why people are downvoting you?
- irrational 5y agoI haven't been given time to read the documentation. I was told TS is simple enough that I can just figure it out on the fly.
- mbrodersen 5y agoWell you have been told wrong. However it only takes about an hour to read the type docs. So take the time why not? Isn’t that better than being frustrated?
- awestroke 5y agoTry fixing the problems
- irrational 5y agoThat is exactly what is taking 99.99+% of the development time. Fixing the problems with typescript. My JS code has no issues.
- 5y ago
- ryanmarsh 5y agoWhat can be done with index access really blew my mind. https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html https://www.typescriptlang.org/docs/handbook/2/indexed-acces...
- spaetzleesser 5y agoAs mainly C# programmer I am getting quite jealous of TypeScript. Seems there is a lot of really interesting stuff going on there.
- chana_masala 5y agoAnders Hejlsberg happens to be the creator (?) of both!
- tus89 5y ago> Well, arrays and objects are quite special in JavaScript. If you pass them to a function it will pass the reference to the array or object which means it will mutate the original array Unlike every other language that passes arrays by value. Ye gad.
- deleted 5y ago[deleted]
- j1elo 5y agoShort comment about the 'unknown' type: TypeScript 4.4 had me learning about it very recently, because 'unknown' has been made the default type in 'catch (error)' clauses [0]. So most of our code in 'catch' blocks suddenly didn't compile any more after an unsuspecting update of the TS version. Which is a good thing, because in reviewing those I found several places where incorrect assumptions were being made about the type of error that would be caught. (side note: TypeScript does not follow SemVer; they just promise to avoid breaking changes in Patch updates, but don't promise anything won't break in Minor updates [1]) [0]: https://devblogs.microsoft.com/typescript/announcing-typescript-4-4/#use-unknown-catch-variables https://devblogs.microsoft.com/typescript/announcing-typescr... [1]: https://github.com/microsoft/TypeScript/issues/14116#issuecomment-280410804 https://github.com/microsoft/TypeScript/issues/14116#issueco...
- plondon514 5y agoWe enjoyed this post so much we turned it into an interactive tutorial, you can take the tutorial for free without signing up here: https://codeamigo.dev/lessons/start/96 https://codeamigo.dev/lessons/start/96
- EnderShadow8 5y agoNote: don't use typeof x === 'object' to check whether something is a valid object, because it will return true for arrays as well. Arrays are objects, so this is expected behaviour.
- hardwaresofton 5y agoArray.isArray[0] is your friend [0]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- IggleSniggle 5y agoDid anybody else have their brain do a weird backflip seeing `Array.isArray[0]`?? Object.getOwnPropertyDescriptors(Array.isArray) /* { '0': { value: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray', writable: true, enumerable: true, configurable: true }, length: { value: 1, writable: false, enumerable: false, configurable: true }, name: { value: 'isArray', writable: false, enumerable: false, configurable: true } } */
- panzerklein 5y agoHow did you get that result? I only see length and name.
- IggleSniggle 5y agoWell, it was a kind of a joke intended for the folks whose brain saw the comment the same way I did. I got the result by applying the footnote to the object, as half-suggested by syntax of the parent: Array.isArray[0] = urlString
- Etheryte 5y agoThe core problem here is that you don't actually want to check if something is an object, but whether it matches the Human type. The correct way to do that is to define a type guard [0], for example: function isHuman(input: any): input is Human { return ( Boolean(input) && Object.prototype.hasOwnProperty.call(input, "name") && Object.prototype.hasOwnProperty.call(input, "age") ); } There are libraries which can automate this for you which is the route I would recommend if you need to do this often. As you can see, the code to cover all edge cases such as `Object.create(null)` etc is not trivial. [0] https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards https://www.typescriptlang.org/docs/handbook/advanced-types....
- throwanem 5y agoThe third example describes something useful in record types, but goes about it in what seems an odd way, and ends up suboptimal as a result. I'd instead use an object type like this: type Human = { name: string; age: number; } which also enforces value types in the compiler, rather than requiring runtime guards.
- 3np 5y agoI think the example type is useful for unvalidated input data e.g. from an API call. Or an update function for a DB abstraction. Internally in the backend, you’d still use the type you just posited.
- throwanem 5y agoEh. A good ORM provides type definitions from model definitions, which is one way I've found ORMs more useful in TS than JS, and I'd more likely use a runtype or a decoder to both validate and type inbound data than roll my own interface for it. On review of documentation, I was actually pretty off base in grandparent comment. The real use case for Record appears to be when you need a map type whose keys are both explicitly enumerated and defined elsewhere, ie in a union, enum, or otherwise unrelated object type. Rather than duplicating the keys, you can use Record<someUnion, V> or Record<keyof typeof someEnum, V> and only have to make one change to update both. For the "arbitrary keys, known value types" case I mentioned earlier, an object type with an index signature works fine and may be more legible.
- chana_masala 5y ago> an object type with an index signature works fine and may be more legible. If I understand you correctly, that's exactly what a Record is underneath
- throwanem 5y agoMore or less. There are extra steps involved with a Record, but they work the same iirc.
- lifthrasiir 5y agointerface Person { [key: AllowedKeys]: unknown } This is one of annoying aspects of TypeScript. The following should work (in fact, this is how `Record<K, V>` is defined in lib.es5.d.ts after all): type Person = { [key in AllowedKeys]: unknown }; Note the switch from interface to type and `:` replaced with `in`. The point is that the `in` syntax (conceptually expanded into multiple fields) subsumes the `:` syntax (a generic type ascription) and is only available as a mapped type, which is distinct with an interface type. The error message does mention this, but if you don't know what is the mapped type you are left with no clues.
- jeswin 5y agoHere's another. Instead of returning Sometype|undefined from a function which may or may not have a value to return (such as searchCustomer), return Sometype|null. That forces the function to return a value that's explicitly intended rather than defaulting from a missed out if-else codepath. This is useful since JS is often imperative style code.
- hamstercat 5y agoThe difference between null and undefined in JavaScript is something I wished had never been implemented. Other languages refer to null as their billion dollar mistake, but somehow JavaScript got 2 of them with slightly different but sometime identical behaviour. I would defer to eslint to prevent this particular issue if you care about it, this allows you to set rules in your own code without any impact to the outside world. I have only seen null vs undefined lead to 2 things in my experience: mistakes and bikeshedding.
- bobbylarrybobby 5y agoI've always liked the two-nulls solution in JS. `undefined` is a runtime-generated missing value, whereas `null` is a compile-time author-supplied missing value. In other words `undefined` is a "pulled" missing value, `null` a "pushed" missing value. Any feature can be misused, but having the distinction is certainly helpful.
- mikeryan 5y agoI agree. I can understand the parent but I like these distinctions and Typescript makes them easier to deal with for me
- lukifer 5y agoI'm fond of this distinction as well. One could also parse it semantically as `undefined` meaning "unknown unknown" vs `null` being a "known unknown" (or "this value left intentionally blank"). Where I think it falls down in practice, is that JS still treats undefined as a legitimate pseudo-value, as opposed to a read-only return result for a missing key. So for instance, `x=[0,1]` and `x=[0,1,undefined]` will both return undefined for `x[2]`, and it takes jumping through some hoops to know if that value was undefined on purpose, or if the key is simply not found. If I had my druthers, attempting to set a value as undefined would either throw a fatal error, or be an alternate syntax to unset a value (such that `x.length` would equal 2 in both examples above).
- presentation 5y agoI actually don't really like Record types in the way people/library maintainers often use them - the type-checker asserts that values are actually present for all the specified keys, which is fine if the objects with the Record type really were exhaustive; but instead I often see them used where the reality of the data is a Partial<Record> - some keys are missing. Something about the abstraction causes people to misuse it frequently.
- e1g 5y agoYep, and in your own code you can tell TS to verify your property access with the setting `noPropertyAccessFromIndexSignature` (https://devblogs.microsoft.com/typescript/announcing-typescript-4-2/#no-property-access-index-signature https://devblogs.microsoft.com/typescript/announcing-typescr...) The TS crew did discuss having a "pedantic" mode, which is stricter than "strict", but I don't think it's on the roadmap any more.
- jsf01 5y agoThat one as well as the noUncheckedIndexedAccess ought to be defaults when in strict mode.
- bilalq 5y agoYou pretty much always have to define your record type with `| undefined` tacked on to the value type parameter. With that, the problem mostly goes away.
- lugged 5y agoWhat's the point of typing things if you have to constantly typecheck them anyway?
- presentation 5y agoYeah, but I use libraries that don’t do that, and have teammates that don’t care about this
- mwhnrt 5y agoI like your tone!
- cstrnt 5y agoThank you very much :)
- cunningfatalist 5y agoNice article, I like it. I can recommend "Programming TypeScript" by Boris Cherny (O'Reilly, 2019) and "Effective TypeScript" by Dan Vanderkam (O'Reilly, 2019), if you want to learn more like this.
- porker 5y agoAnd https://exploringjs.com/tackling-ts/ https://exploringjs.com/tackling-ts/
- charesjrdan 5y agoIs there ever a reason to use interface over type? From what I’ve seen it looks like they can both do the same thing but with slight differences in syntax
- iaml 5y agoI prefer types over interfaces because of one simple difference: if you use vs code and hover over type alias, it expands it and shows everything inside, while for interfaces it just shows the name.
- shadowgovt 5y agoThey are very similar, but they are subtly different in ways that might matter, depending on what you want to do. A type is statically-"tagged" data from the typechecker's point of view. Even if `Foo` and `Bar` are two types with the exact same fields, the typechecker won't let you use as Foo as a Bar or vise-versa unless you've explicitly declared that Foos are Bars (via type aliasing or inheritance). An interface declares a whole category of types that are equivalent: anything with the same "shape" as the interface will count as the interface. So you can pass objects, child objects, objects with additional fields attached, etc. to an interface input; if the thing has the fields the interface cares about, it'll accept it. Which you want to use depends on what precisely you intend to do, but interfaces are handy in TypeScript where they may be less useful in some other languages because the underlying JavaScript is so "duck-typed" and sloppy on what it means for something to "have a type;" interfaces often model more accurately the behavior of "native" JavaScript functions (that will take an argument, assume it's an object, and just start touching some fields on it without caring whether more fields exist or not).
- csnweb 5y agoYes interfaces can be merged: https://www.typescriptlang.org/docs/handbook/declaration-merging.html https://www.typescriptlang.org/docs/handbook/declaration-mer..., which can be useful when working with external libraries.
- henriks 5y agoOne detail I stumbled upon the other day is that interfaces can use the `this` keyword to refer to the type implementing the interface. This isn't supported for types afaik. https://www.typescriptlang.org/docs/handbook/advanced-types.html#polymorphic-this-types https://www.typescriptlang.org/docs/handbook/advanced-types....
- skywal_l 5y agoUtility Types[0] will help you get to the next level on Typescript. It's important to know them and know how and when to use them. [0] https://www.typescriptlang.org/docs/handbook/utility-types.html https://www.typescriptlang.org/docs/handbook/utility-types.h...
- mithusingh32 5y agoWow, thanks for this. I wasn't even aware of these. I'm surprised I rarely see these in courses/tutorial. These should be like day 1 material.
- shadowgovt 5y agoTS has been around long enough that it suffers from the 'obsolete tutorial' problem (one I first observed learning C++): many of the utility types didn't exist when many of the popular tutorials were first written.
- skywal_l 5y agoTypescript is actually a great language. And with those utility types, you can do pretty fun stuff like, for example, you want to mutate a type so that some fields become mandatory: type Ensure<T, K extends keyof T> = T & { [U in keyof Pick<T, K>]-?: T[U] }; class A { foo?: number; bar?: number; baz?: number; } type MandatoryFields = "foo" | "baz"; type B = Ensure<A, MandatoryFields>; const b: B = { foo: 42 }; Here, ts will complain that b is missing baz.
- CuriouslyC 5y agoWhy write code like that, instead of extending the class with a mandatory property? The above code is going to be inscrutable to a lot of engineers, and this isn't something like an ORM where there's a good reason for that.
- goto11 5y agoUtility types are useful for example in the React API. You have a "state" defined as a set of properties. Then you have a setState() method where you return the set of properties you want to update, which may be a subset of the full state. So if the type of the component state is TState, then the return type of setState() can be defined as Partial<TState>.
- Fedelaus 5y agoI think the unknown example is good but also somewhat confusing, because implicit typing would understand what set of types could be in that array at that moment. Is there another example someone could give for unknown which isn't handled by implicit typing?
- shadowgovt 5y agointerface ServerResponse { data: unknown; } ... this is the most common way I see unknown used. Then when you fetch data from the server, you are reminded by the compiler that you should do some duck-type checking on it to make sure it's shaped correctly (since responses from a server can be any shape; is it a 200 with your data, or did a caching layer vend you an old version of this data structure, or is something catastrophically wrong and you're seeing a 200 where the payload is HTML saying "Set up your apache server," etc.) BTW, TypeScript has another useful tool for tying the runtime typing and static typing together: type guards. function isUserRecord(x: unknown): x is UserRecord { return (x as UserRecord).name !== undefined; } This is a boolean function but the type system understands that in codepaths where it returns true, the 'x' argument is known to have the UserRecord type. Great for codifying your type-discernment logic.