I haven't done a lot of Typescript, but I've done at least a couple of month's worth now, and every time I have to type "as" my inner Haskell programmer screams.
If I could add one feature to Typescript it would be something like "as" that actually validates the result against the type system and can fail. Unfortunately, that's way, way easier said than done. It's the bad type of keyword that has unbounded runtime cost because it would have to be a runtime comparison, and there are a lot of design questions about how to write it. However, I still petulantly want it even though I can hardly define it. "zod" is pretty good but you can see how trying to add that as a "keyword" is nightmare fuel for a language-level change.
"every time I have to type "as" my inner Haskell programmer screams." - most of the times you don't have to. You choose to.
"If I could add one feature to Typescript it would be something like "as" that actually validates the result against the type system and can fail." - I don't think it's fair to expect that since most of the statically typed languages will not guarantee things in runtime unless you specifically run a validation code in runtime.
There's also type guards and good old self-written validation functions you can use.
In addition to exploring `satisfies` as a better `as` (compile checks, that don't assert), you may also be looking for `is` aka Type Guards (runtime checks that assert types).
If you have a validator function `function isSomeSpecificType(obj: unknown): boolean` you make it a Type Guard by changing the return type to be the type assertion you need: `function isSomeSpecificType(obj: unknown): obj is SomeSpecificType`. Typescript's narrowing is pretty good about using Type Guards to good advantage.
The "satisfies" keyword may be what you are missing. Most of the cases I used to need "as" (usually weirdly permissive types from some lib) can be nudged in line with a "satisfies"
I wonder what you're doing that you need to type it so often. I almost never use it in application code (outside of tests and generic utilities).
There are some techniques that aren't immediately obvious. Look into...
- type guards
- pushing constraints up: `function print(i: Invoice & { issueDate: string })` is better than `assert(i.issueDate)`
- discriminated unions