8 ms·
`satisfies` is my favorite TypeScript keyword (2024)
- ghtbircshotbe 1y agoLots of people seem to love typescript, but as far as I can tell it's adding features from c++ which lots of people seem to hate. Am I missing something?
- jonny_eh 1y ago> This keyword is a bit esoteric and not very common, but it comes in handy in some scenarios where you’d otherwise pull your hair out. Typescript in a nutshell. That said, satisfies is a good keyword!
- epolanski 1y ago> TypeScript is a wonderfully advanced language though it has an unfortunately steep learning curve An extremely steep one. The average multi-year TypeScript developer I meet can barely write a basic utility type, let alone has any general (non TypeScript related) notion of cardinality or sub typing. Hell, ask someone to write a signature for array flat, you'd be surprised how many would fail. Too many really stop at the very basics. And even though I consider myself okay at TypeScript, the gap with the more skilled of my colleagues is still impressively huge. I think there's a dual problem, on one side type-level programming isn't taken seriously by the average dev, and is generally not nurtured. On the other hand, the amount of ideas, theory, and even worse implementation details of the TypeScript compiler are far from negligible. Oh, and it really doesn't help that TypeScript is insanely verbose, this can easily balloon when your signatures have multiple type dependencies (think composing functions that can have different outputs and different failures).
- undeveloper 1y agothese are things most developers don't know how to do in most language's type systems. I think only rust with its focus on functional roots has seen similar focus on utilizing its type system to its fullest extent.
- lloydatkinson 1y agoTypeScript codebases I've seen generally seem to have the widest demonstration of skill gap versus other languages I use. For example, I don't ever see anyone using `dynamic` or `object` in C#, but I will often see less skilled developers using `any` and `// @ts-ignore` in TypeScript at every possible opportunity even if it's making their development experience categorically worse. For these developers, the `type` keyword is totally unknown. They don't know how to make a type, or what `Omit` is, or how to extend a type. Hell, they usually don't even know what a union is. Or generics. I sometimes think that in trying to just be a superset of JavaScript, and it being constantly advertised as so, TypeScript does not/did not get taken seriously enough as a standalone language because it's far too simple to just slot sloppy JavaScript into TypeScript. TypeScript seems a lot better now of having a more sane tsconfig.json, but it still isn't strict enough by default. This is a strong contrast with other languages that compile to JavaScript, like https://rescript-lang.org/ https://rescript-lang.org/ which has an example of pattern matching right there on the home page. Which brings me onto another aspect I don't really like about TypeScript; it's constantly own-goaling itself because of it's "we don't add anything except syntax and types" philosophy. I don't think TypeScript will ever get pattern matching as a result, which is absurd, because it has unions.
- ervine 1y agoOn the other hand, would we even be talking about it if it hadn't stuck to its goals?
- fourthark 1y agoIt will get pattern matching when JS does. Not certain yet but in progress. https://github.com/tc39/proposal-pattern-matching https://github.com/tc39/proposal-pattern-matching
- ibejoeb 1y agoThat proposal is really dragging though. And typescript needs as much work because that's where the real power is. We need discern thing like match (x) { "bob": ..., string: ..., () => Promise<void>: ..., () => Promise<string>: ..., } with exhaustiveness checking for it to be truly useful.
- ForHackernews 1y agoHonestly I just use TypeScript to prevent `1 + [] == "1"` and check that functions are called with arguments. I don't care about type theory at all and the whole thing strikes me as programmers larping (poorly) as mathematicians.
- epolanski 1y agoI couldn't care less about mathematics, but I do care about making impossible state impossible and types documenting the domain. If you type some state as: isLoading: boolean result: Foo hasError: boolean errorMessage: string | null then you're creating a giant mess of a soup where the state of your program could have a result, be loading and an error at the same time. If you could recognise that the state of your program is a sum of possible states (loading | success | error), and not their product as the type above you could highly simplify your code, add more invariants and reduce the number of bugs. And that is a very simple and basic example, you can go *much* further, as in encoding that some type isn't merely a number through branded types, but a special type of number, be it a positive number between 2 and 200 or, being $ or celsius and avoiding again and entire class of bugs by treating everybody just as an integer or float.
- what 1y ago>encoding that a number is between 2 and 200 What’s the point of this level of autism when you still have to add run time checks?
- kennywinker 1y agoFor a function setVelocity() that can accept 1..<200. You call it with numbers that you enter directly and types tell you something that would otherwise be a comment on the function, or you do runtime checks elsewhere, and the type becomes proof that you checked them before handing it into the function. Btw, using “autism” to mean “pedantry” leaves a bit of a bad taste in my mouth. Maybe you could reconsider using it that way in the future.
- samdoesnothing 1y agoI have mixed feelings about Typescript, I hate reading code with heavy TS annotations because JS formatters are designed to keep line widths short, so you end up with a confusing mess of line breaks. Pure JS is also just more readable. Also you can so easily go overboard with TS and design all sorts of crazy types and abstractions based on those types that become a net negative in your codebase. However it does feel really damn nice to have it catch errors and give you great autocomplete and refactoring tooling.
- locknitpicker 1y ago> I have mixed feelings about Typescript, I hate reading code with heavy TS annotations because JS formatters are designed to keep line widths short, so you end up with a confusing mess of line breaks. Pure JS is also just more readable. That's not a TypeScript issue, it's a code quality issue and a skill issue. Anyone can put together an unintelligible mess in any language.
- afavour 1y ago> Too many really stop at the very basics. I don’t think that means it has a steep learning curve. It just means the basics suffice for a ton of TypeScript deployments. Which I personally don’t see as the end of the world.
- vosper 1y agoYes, to me this is a biggest feature of Typescript: A little goes a long way, while the advanced features make really cool things possible. I tend to think of there being two kinds of Typescript - Application Typescript (aka The Basics, `type`, `interface`, `Record`, unions etc...) and Library Typescript which is the stuff that eg Zod or Prisma does to give the Application Typescript users awesome features. While I aspire to Library TS levels of skill, I am really only a bit past App TS myself. On that note I've been meaning to the the Type-Level Typescript course [0]. Has anyone taken it? https://type-level-typescript.com/ https://type-level-typescript.com/
- pcthrowaway 1y ago> Hell, ask someone to write a signature for array flat, you'd be surprised how many would fail. To be clear, an array flat type: type FlatArr<Arg extends unknown[]> = Arg extends [infer First, ...(infer Rest)] ? First extends unknown[] ? [...First, ...FlatArr<Rest>] : [First, ...FlatArr<Rest>] : []; is far from basic Typescript. The average Typescript dev likely doesn't need to understand recursive conditional types. It's a level of typescript one typically only needs for library development. Not only have I never been expected to write something like this for actual work, I'm not sure it's been useful when I have, since most of my colleagues consider something like this nerd sniping and avoid touching/using such utilities, even with documentation.
- wk_end 1y agoIf I saw that in a PR I would push very hard to reject; something like that is a maintenance burden that probably isn’t worth the cost, and I’ve been the most hardcore about types and TypeScript of anyone of any team I’ve been on in the past decade or so. Now, that said, I probably would want to be friends with that dev. Unless they had an AI generate it, in which case the sin is doubled.
- deleted 1y ago[deleted]
- 8note 1y agolooking back at them is also real hard to debug. you dont get a particularly nice error message, and a comment or a test would tell better than the type what the thing should be looking like
- probabletrain 1y agoI think there’s a difference between what’s expected/acceptable for library code vs application code. Types like this might be hard to understand, but they create very pleasant APIs for library consumers. I’ve generally found it very rare that I’ve felt the need to reach for more complex types like this in application code, however. RXJS’s pipe function has a pretty complex type for its signature, but as a user of the library it ‘just works’ in exactly the type-safe way I’d expect, without me having to understand the complexity of the type.
- madeofpalk 1y ago> Too many really stop at the very basics. As someone who knows slightly more than the basics, and enough to know about the advanced stuff that I don't know about, this is the correct place to stop. I would much rather restructure my javascript than do typescript gymnastics to fit it into the type system.
- IceDane 1y ago[flagged]
- ervine 1y agoYou can restructure your JS to avoid some crazy verbose TS though, sometimes. I think that's the point they were making. Why be so hostile?
- IshKebab 1y agoI agree. The advanced stuff mostly exists in order to allow writing type annotations for JavaScript libraries that have APIs that are very dynamic. If you're purely writing Typescript then you mostly don't need it.
- imiric 1y agoYou're right, but that begs the question: does a type system really require such complexity? I'm aware that type theory is a field in and of itself, with a lot of history and breadth, but do developers really need deep levels of type flexibility for a language to be useful and for the compiler to be helpful? I think TypeScript encourages "overtyping" to the detriment of legibility and comprehension, even though it is technically gradually typed. Because it is so advanced and Turing complete itself, a lot of brain cycles and discussion is spent on implementing and understanding type definitions. And you're definitely right that it being verbose also doesn't help. So it's always a bittersweet experience using it. On one hand it's great that we have mostly moved on from dynamically typed JavaScript, but on the other, I wish we had settled on a saner preprocessor / compiler / type system.
- rjh29 1y agoThe idea is to make libraries preserve as much type information as possible, as a principle. Once type information is erased it can't be restored. For regular application code you don't need to use those features.
- imiric 1y agoBut regular application code also contains libraries. Type information is useful even if you're the only user of those APIs. My point was more related to the level of expressiveness required of a type system in order to allow a programmer to produce reliable code without getting in their way. I think TypeScript leans more towards cumbersome than useful. For example, I'm more familiar with Go's type system, which is on the other side of that scale. It is certainly much less expressive and powerful than TypeScript, and I have found it frustrating and limiting in many ways, but in most day-to-day scenarios it's reasonably adequate. Are Go programs inherently worse off than TypeScript programs? Does a Go programmer have a worse experience overall? I would say: no.
- rjh29 1y agoThey're completely different languages, Javascript is dynamically typed, not sure how useful such a comparison is. TS's type system evolved out of a desire to encode the type relations of JS functions, often native ones, which are very dynamic and polymorphic. When writing application code you can keep things simple, but trying to represent all the ways types can change for the native libraries is harder.
- stefan_ 1y agoThis is the bell curve meme, and you are in the middle telling us "template metaprogramming in C++ is amazing".
- dzonga 1y agotypescript is largely a result of solving a non-existent problem. Yeah JS is finicky & has foot-guns, however they're ways around those foot guns that don't involve typescript. Rich Hickey in 10 Years of Clojure & Maybe Not then the Value of Values - lays this out - though not meant at typescript but static types in general. the thing most people don't have proper Javascript fundamentals. Function signatures: JSDoc works Most types - use Maps | Arrays if a value doesn't exist in a map we can ignore it. There's also the safe navigation operator. Instead of mutable objects - there's ways around this too. Negating types again.
- fenomas 1y agoUh, among several other issues with this, what use are JSDoc comments for typing, without typescript to check them?
- locknitpicker 1y ago> typescript is largely a result of solving a non-existent problem. Claiming that lack of static type checking is a non-existent problem is quite a bold claim. Care to offer some details to substantiate your claim?
- monkpit 1y ago> ask someone to write a signature for array flat Out of curiosity - what do you think is a satisfactory answer here? My answer would vary wildly based upon more details, but at the most basic all I can think you could guarantee is Array<unknown> => Array<unknown>?
- epolanski 1y agoIn an interview I'd be happy just seeing some reasoning. IRL I'd be happy with someone at least searching for a definition and trying to learn from it. I've asked this question multiple times as implementing array flatten used to be our go to ice breaker question, and many devs had no issues reasoning and finding an okay type definition.
- mook 1y agoIt's also terribly documented. As an example, I don't think `satisfies` is in the docs outside of release notes. There's lots more stuff like that, which makes using it kind of frustrating.
- lelandfe 1y agoPreach. It’s astonishing how much necessary documentation lives as unchanging footnotes on TS releases. https://www.google.com/search?q=site%3Ahttps%3A%2F%2Fwww.typescriptlang.org+%22satisfies%22 https://www.google.com/search?q=site%3Ahttps%3A%2F%2Fwww.typ...
- cynicalcoder 1y ago>And even though I consider myself okay at TypeScript, the gap with the more skilled of my colleagues is still impressively huge. Maybe they're smart, but the even smarter dev would avoid unnecessary complexity in the first place.
- paulddraper 1y agoNot steep so much as deep. There’s a lot you can do in TypeScript. But you don’t have to do it. And TS existed successfully a long time without those features.
- mohas 1y agoto our defense, we want to build stuff not become ts wizards. also I've worked with libraries with heavy heavy typing that it was a nightmare if you wanted to use their lib in any other way than what they have imagined.
- knallfrosch 1y agoTypescript types often devolve into keyof typeof[number] ? uppercase (myNum) On the other hand, there isn't much Omit, readonly, mutable in existing code bases, so devs have nowhere to learn but documentation. Then the ground shifts again and –what should be basic stuff – enums are banned, because erasableSyntaxOnly makes life so much easier.
- Exoristos 1y ago"There basics," well understood and judiciously applied, is where the bulk of TypeScript's value lies.
- locknitpicker 1y ago> "There basics," well understood and judiciously applied, is where the bulk of TypeScript's value lies. Yes, precisely. OP is also completely oblivious to the fact that TypeScript is designed to help developers gradually onboard legacy JavaScript projects and components, which definitely don't require arcane and convoluted type definitions to add value.
- locknitpicker 1y ago> The average multi-year TypeScript developer I meet can barely write a basic utility type, let alone has any general (non TypeScript related) notion of cardinality or sub typing. Hell, ask someone to write a signature for array flat, you'd be surprised how many would fail. I think you're both exaggerating your blanket accusations of incompetence and confusing learning curve with mastering extremely niche techniques akin to language gotchas.
- baxuz 1y agoBeing a JS/TS one-trick pony all my career, how does it compare to other languages? I don't really see much difference, except if comparing with some C++ shenanigans.
- SkyPuncher 1y agoI stopped doing anything advance because I realized nobody actually wanted to do all of the advanced stuff. None of the NPM community does anything more than the basics. Frankly, I prefer it that way. A lot of the advance stuff doesn’t actually enable any new functionality. It only shortens the code paths for implementing.
- yieldcrv 1y agothe cool thing about Typescript is that you never have to know any of this to deliver highly performant enterprise scale software
- michaelcampbell 1y agoYou can do that with assembly and not know ANY high level language. You might be interested in reading PG's treatise on "the blub paradox".
- coolThingsFirst 1y ago[dead]
- Muromec 1y agoCan you even do that? I though you could only enterprise in secure languages, like Java
- yieldcrv 1y ago2010 you rang? The language isn’t the bottleneck
- another_twist 1y agoI think this is spot on. TS goes very very far without the gymnastics. Its good to know these things, but not even close to necessary to be productive. Not to mention IDE support for TS is on a very different level conpared to the shitshow that is Javascript. Also, Angular dev spotted :)
- prmph 1y agoWhen you are building even moderately large non-trivial real world software with JS, you would thank your stars that TS exists and that it has features like this. It's amazing how quickly the basic concepts of software engineering become inadequate when they run up against the real world. For example, a naive engineer might think, ah, databases have this oFFSET clause, good, I'll use, unaware that is a foot gun for real world performance. Or they may think the DELETE operation on DBs is a normal thing, unaware that in most cases it should NOT be used at all. Or they might think loops are idiomatic, unaware that when you are writing large software you should and can probably almost eliminate loops (unless you are using a DSL like SQL extensions, config languages, etc) Or they may be unaware of the thorny issues around queues (or even why they might be necessary in the first place) and concurrent access to data. Or they might not understand why the dogma of separating content and presentation is nonsensical in many situations. Etc.
- ptrl600 1y agoThis is wordier than just "as const", what advantage does it give? (I am a newbie and genuinely don't know) edit: perhaps the advantage only comes into play for mutable values, where you want a narrower type than default, but not that narrow. Indeed, this is covered in the article, but CTRL+F "as const" doesn't work on the page for whatever reason, so I missed it.
- iddan 1y agoWith as const you can’t verify against another interface
- bastawhiz 1y agoI've really only found benefit on the return type of functions, when you can say that a type parameter satisfies a type (with the return type being a boolean). This let's you use `if (isPerson(foo))` and typescript will narrow the type appropriately in the conditional
- reissbaker 1y agoThe satisfies keyword is quite different than "as const." What it does is: 1. Enforce that a value adheres to a specific type 2. But, doesn't cause the value to be cast to that type. For example, if you have a Rect type like: type Rect = { w: number, h: number } You might want to enforce that some value satisfies Rect properties... But also allow it to have others. For example: const a = { x: 0, y: 0, w: 5, h: 5 }; If you wrote it as: const a: Rect = // ... TypeScript wouldn't allow you to also give it x and y properties. And if you did: as Rect at the end of the line, TypeScript would allow the x, y properties, but would immediately lose track of them and not allow you to use them later, because you cast it to the Rect type which lacks those properties. You could write an extra utility type: type Location = { x: number, y: number }; const a: Location & Rect = // ... But that can get quite verbose as you add more fields. And besides: in this example, all we actually are trying to enforce is that the object is a Rect — why do we also have to enforce other things at the same time? Usually TS allows type inference for fields, but here, as soon as you start trying to enforce one kind of shape, suddenly type inference breaks for every other field. The satisfies keyword does what you want in this case: it enforces the object conforms to the type, without casting it to the type. const a = { x: 0, y: 0, w: 5, h: 5 } satisfies Rect; // a.x works Then if someone edits the code to: const a = { x: 0, y: 0, width: 5, height: 5 } satisfies Rect; TypeScript will throw an error, since it no longer satisfies the Rect type (which wants h and w, not height and width).
- Waterluvian 1y agoI’m so frustrated by satisfies because it eliminates optional properties. I want an object of ‘LayerConfig’ elements where each key is the name of a possible layer. Without ‘satisfies’ I have to name every layer twice in my config. But with it, I can’t have optional properties (eg. Half the layers are fine with the default values for some properties). The best I’ve found is a hack that uses a function. But this whole thing where my key literals widen into “string” is a constant annoyance to otherwise very elegant code.
- iddan 1y agoThen either make the properties optional or use Partial on the type you are satisfying
- theogravity 1y agoThe second example confuses me. The Person type has isCool: boolean, not an explicit true. How does using satisfies here pass coolPeopleOnly?
- auxiliarymoose 1y agoYou can sorta think of `satisfies Foo` as "the type is exactly the literal value, but also make sure the value could be used in the place of a Foo"
- nrhrjrjrjtntbt 1y agoWhy? why make your code so complex you even hit this problem. Just use the type: const x: Thetype = .... I am not keen on as const either. Just program to interfaces. It is a better way to think IMO.
- ibejoeb 1y agoThe author gets into that. `Thetype` might be complex. It also protects you from overgeneralizing, like casting to and from `unknown` to escape the type checker. type Current = { kind: "ac" | "dc"; amps: number; } type Dc = { kind: "dc"; amps: number; } const ac: Current = { kind: "ac", amps: 10000000, } const handleDc = (thing: Dc) => {} const badConvert = (c: Current) => ({...c, kind: "dc"}); /** * Argument of type '{ kind: string; amps: number; }' is not assignable to parameter of type 'Dc'. Types of property 'kind' are incompatible. Type 'string' is not assignable to type '"dc"'.(2345) */ handleDc(badConvert(ac)); const goodConvert = (c: Current) => ({ ...c, kind: "dc", } satisfies Dc); handleDc(goodConvert(ac)); /** * Object literal may only specify known properties, and 'bar' does not exist in type 'Dc'. */ const badConvert2 = (c: Current) => ({ ...c, kind: "dc", bar: "qwerty" } satisfies Dc);
- nrhrjrjrjtntbt 1y agoI see. I dont mind this use case as much. It is like a hint.
- ibejoeb 1y agoExactly. It's a safer assertion, as the author points out. You can work without it, but it's a little more cumbersome and involves creating the otherwise unnecessary, transient intermediate types.
- another_twist 1y agoThe bad convert is actually wrong. It should be refactored to an equality check and throw an error if account kind is not "dc". The compiler is correct and its not a good idea to work around this issue.
- retired_account 1y agoIn my personal projects, I’m a fan of using satisfies to check Zod definitions against the interfaces they validate. I find the base interfaces easier to read at a glance than derived types, especially in an editor’s hover view. Though, nullable fields might get weird, iirc.
- MrJohz 1y agoYeah, I believe that doesn't quite work correctly for nullable fields or cases where the Zod type would be a subtype of the declared type. But it's a really useful technique, because it's a lot easier to work with types you've declared in TypeScript than the ones Zod generates. I'm sure there's scope for a validation library that is designed around the user providing a TypeScript type and then producing an error if the validation doesn't match that type.
- Androider 1y ago80% of the value of TypeScript is that it will tell you when when you changed or added a parameter and forgot to update it everywhere, you doofus. The other 20% is that it keeps coding agents from going too far off the rails. Trying to use the type system as a metaprogramming language is only valuable as a fun exercise, but of negative value in real world projects.
- another_twist 1y agoThis thread is weird, also spot on, not sure why its downvoted. I am happy when the IDE spots my dufusness.
- sethaurus 1y agoThat's a little ungenerous. Richer types are not intrinsically about metaprogramming, they just let you model your domain more accurately so you can turn runtime errors into build-time errors. If your system already has natural constraints, you get to document them in a machine-checkable way.
- kayson 1y agoSo satisfies prevent you from mutating then? Otherwise you could just change name afterwards...
- int_19h 1y agoIt prevents you from mutating via the reference that you obtain from `satisfies` without casting its type, yes (or rather more precisely, you can mutate it, but only to the one allowed value). However, the object can still be mutated via other references to it. TypeScript is full of holes like this in the type system - the problem is that they are trying to bolt types and immutability onto a hot mess that is JS data model while preserving backwards compatibility.
- preommr 1y agomeh article > Why is the name of person1 of type string and not the literal "Jerred"? Because the object could be mutated to contain any other string. Not really, if you declare {name: "Jerred" as const}, it's still mutable. Typescript just decided that given certain primitive-like types like strings, it's preferrable to infer string rather than as constant. Satisfies offers the opposite AS A MOSTLY ORTHOGONAL design decision. It's a happy byproduct that the type inference's behavior is changed. And this is relevant because it affects technically important situations like deeply nested values NOT being narrowed, but it's also just not a good mental model for what it's supposed to do. People should assume that given a type literal, that it just infers the widest typing. Incidental behavior that arises from using 'as const', or 'satisfies' should follow it's semantic purpose. If you want specific typing, just build the type - don't use hacks. Satisfies is useful because sometimes you have something with some typing (often as const for something like utils), that you also need to make sure satisfies some other typing - almost as a constraint. Would not surprise me if ts team released a keyword that did type inference with narrowest (like as const, but without the readonly).
- amake 1y ago99% of my use of `satisfies` is to type-check exhaustivity in `switch` statements: type Foo = 'foo' | 'bar'; const myFoo: Foo = 'foo'; switch (myFoo) { case 'foo': // do stuff break; default: myFoo satisfies never; // Error here because 'bar' not handled }
- inlined 1y agoNice. I didn’t know I can now replace my “assertExhaustive” function. Previously you could define a function that accepted never and throws. It tells the compiler that you expect the code path to be exhaustive and fixes any return value expected errors. If the type is changed so that it’s no longer exhaustive it will fail to compile and (still better than satisfies) if an invalid value is passed at runtime it will throw.
- preommr 1y agoI thought the same thing. I also have an assert function I pull in everywhere, and this trick seemed like it would be cleaner (especially for one-off scripts to reduce deps). But unfortunately, using a default clause creates a branching condition that then treats the entire switch block as non-exhaustive, even though it is technically exhaustive over the switch target. It still requires something like throwing an exception, which at that point you might as well do 'const x: never = myFoo'.
- nikeee 1y agoI still keep my assertNever function because it will handle non-exhaustiveness at runtime.
- ervine 1y agohttps://typescript-eslint.io/rules/switch-exhaustiveness-check/ https://typescript-eslint.io/rules/switch-exhaustiveness-che... if that is something you're not aware of!
- mckirk 1y agoI generally do this via a `throw UnsupportedValueError(value)`, where the exception constructor only accepts a `never`. That way I have both a compile time check as well as an error at runtime, if anything weird happens and there's an unexpected value.
- ethmarks 1y agoDoes anyone know what was used to render these code blocks in the article? The mouseover tooltip is extremely cool. I've never seen anything like it before. EDIT: I dug through the codebase and determined that it's using Shiki and TwoSlash for the syntax highlighting and tooltips.
- coolThingsFirst 1y ago[dead]
- rvz 1y ago> TypeScript is a wonderfully advanced language though it has an unfortunately steep learning curve; in many ways it’s the complete opposite of Go. Replace "TypeScript" with "C++" and the same can be said. It is one of the worst languages ever designed and already built on top of a sloppy foundation (Javascript) compared to Go. The language encourages escape hatches and tons of flexibility on how it checks its types and creates the risk of inconsistency to engineers on which rules to adopt and there is always one engineer that will disagree with some settings and argue to turn on/off a rule to defeat the purpose of the language. At this stage, its no better than C++ but significantly slower, and I've seen the same mistakes (enums, allowing "as XYZ" casting, etc) in C++ creeping into TypeScript. Even the entire language parser and type checker is being rewritten in Go. [0] [0] https://devblogs.microsoft.com/typescript/typescript-native-port/ https://devblogs.microsoft.com/typescript/typescript-native-...
- knallfrosch 1y agoTell me when Go is browser ready
- fragmede 1y agoWhen. export GOOS=js export GOARCH=wasm
- another_twist 1y agoMisses the point. Both these languages have their place. Besides there's no benchmarks beyond developers personal opinions that tells us whether a language is browser ready or not.
- another_twist 1y agoI disagree. The speed with which Typescript replaced JS as the default is testament to its strength. I remember back is the good old JS only days you had to assume that all the form values we passed and read were strings and not an integer account number for example. Typescript solves these challenges and that alone eliminates a large class of frankly nonsensical bugs. The reason it is being rewritten in Go is so the compiler can be run at native speeds which is a good thing. Otherwise the only runtime we have available is NodeJS which has its fair share of problems. You can go far with TS with just interface definitions and some generics peppered in for common utilities. The places where all the type gymnastics is necessary are cases I frankly havent encountered in the usual course of development.
- stgr_codes 1y agoThis article shows the kind of overthinking that I hate when it comes to typescript usage. This is also the reason why I'm falling in love with Go. Don't get me started on how this is so unnecessary on the browser (so the utility on this kind of stuff is actually for library development; maybe). Am I the only one that thinks that Typescript waste your time on minutia like this?
- deleted 1y ago[deleted]
- mcintyre1994 1y agoSatisfies is very useful as a library author for testing your types. You can write `typetest` files that don't become part of the bundle but are compiled. One example is that we have a TS library for a JSON-RPC server that is horribly complex on the server side, returning different shapes of output based on input params. I don't think it can be typed with OpenAPI etc, but it can be with Typescript method overloads. But then instead of writing unit tests that either coerce or mock the server into returning each shape, we can write typetests like this to make sure our type juggling provides the exact right types to developers: const rpc = null as unknown as Rpc<SomeApi> const result = await rpc.someApi(input).send() result satisfies { value: { nestedFieldForThisInput: number } } ``` The tradeoff is slightly longer compile times for the library since all this is checked at build time, but it provides a lot of flexibility for testing overloads and utility types in isolation.
- Normal_gaussian 1y agoYou can use multiple tsconfig files to remove the compile time issue; this is quite common for test files anyway. Its not unusual to see one for CI & IDE and one for compilation, the compilation one having a much more limited scope of files.
- prmph 1y agoYeah, the satisfies operator is powerful. One thing it allows you to do is to check that one expression is assignable to a type, without actually declaring or coercing the expression to be of that type. In my experience, here is summary of when you might want to use the various type features: - Using the "as" keyword tries to coerce/cast an expression to be of some type. This is the least safe, since it overrides proper type checking, at least to some extent. However, in many cases it still does some level of type checking, and it is sometimes necessary if you know something the type checker is unable to prove. - Declaring an expression to be of some type before initializing it. This is the strictest, and thus most safe, but sometimes it is inconvenient. You might want types to be inferred, which is a really useful thing sometimes, e.g., in a fluent interface when each step constrains types in additional ways. - The satisfies keyword bridges the gap between the above two: you want to assert/check that the expression is assignable to a certain type (which can be as loose or strict as you want it), whilst still retaining the original type that is inferred for the expression. Unlike "as", you are not overriding the type system. And you are also not actually declaring a type for the expression. I have found this very useful on numerous occasions. Having said that, there is weird (new?) behavior of the satisfies keyword where appending it to an expressions can cause the the expression itself to fail type-checking internally, where it would otherwise be fine. This is strange, the basic premise of satisfies is to check if an expression satisfies a type. If there is a type violation at all, it should be at the expression/type boundary, not inside the expression. It's making it less useful for me.
- benced 1y agoMeanwhile, Python can sometimes verify if something is an int or a string.
- frou_dh 1y agoThe contrived example used in the first half of the post is offputting. Why would you have a function of 1 argument that only accepts a string with a specific value? There's no point taking an argument then - it might as well be a constant inside the function.