7 ms·
Functional Programming with TypeScript's Type System
- nkrisc 3y agoAs wonderfully absurd as this is, I learned more about TypeScript’s type system from this post than I have from its documentation. Entirely possible that PEBKAC, but I’ve found TypeScript’s documentation to be on the worse end of the programming language documentation quality spectrum.
- wooly_bully 3y agoIt’s good for reference but not for discovery. If I already know the general concept (let’s say Template Literal Types) I can get good info on it, but if I start with a question like ‘Is there a way to make sure this string literal starts with “id_”?’ then I find it very hard to know. Random but this is what I’m finding GPT-4 best at: translating random questions into domain terminology + providing examples.
- iudqnolq 3y agomaybe this is just an issue with me but I've not found any way to search the docs. the only thing Google seems to index is the release notes, and going backwards from the release notes to guess the appropriate section of the docs that will explain that concept is really annoying.
- nkrisc 3y agoI can’t even find basic type definitions for standard JS functions. I have to type the function in my IDE and then open the type definition from there. So it works, I guess, but that’s not really how I want to work.
- DangitBobby 3y agoIt's not just you. To learn how to express more advanced types (or learn whether they are even possible to express), I've had to Google, read source code, or scan random medium articles and blogs from tech companies. Rarely have I learned anything new from the TS docs.
- nkrisc 3y agoI learned more from this type definition than anything I’ve ever read about TypeScript’s type system before: interface add extends F { out: this['args'] extends [infer a, infer b] ? a extends Zero ? b : a extends Suc<infer n> ? Suc<apply<add, [n, b]>> : never : never }
- coneonthefloor 3y agoWhat a monstrosity.
- hoelle 3y agoGross. I love it.
- ck45 3y agoRelated: "TypeScripting the technical interview" https://news.ycombinator.com/item?id=35120084 https://news.ycombinator.com/item?id=35120084
- deleted 3y ago[deleted]
- jcparkyn 3y agoI've done my share of weird stuff with TS types before, but I'd never seen the trick of using interfaces to make higher-order functions. Neat.
- deleted 3y ago[deleted]
- Waterluvian 3y agoWhile no actual Turing machine’s tape is infinitely long, I found issues in TypeScript with how finite generics are. You have to define every possible count of generic arguments if you want to preserve their types. And if you go above that count your type system degrades. I think there’s also a maximum of 7 or so before it doesn’t work. Beyond that and the generic type widens. For example, Lodash enumerating types for 2 to 7 generic items per function: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/045220a0682a1f437c08610db4ad6eaf76b2f9f0/types/lodash/common/array.d.ts#L142 https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0452... Admittedly I don’t understand the problem space well. I’ve just seen it happen to me and in others’ code. It might not actually be an issue, or is already fixed.
- SirensOfTitan 3y agoThis was fixed in Typescript 4.0, with the introduction of variadic tuples: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html https://www.typescriptlang.org/docs/handbook/release-notes/t...
- Waterluvian 3y agoOh awesome! Thanks for sharing.
- rdez6173 3y agoFun exploration and exceptionally impractical. Love it.
- firechickenbird 3y agoAt this point I'm wondering if the TypeScript type system can be used for dependant types that would allow formal verification of the programs
- remexre 3y agoThat'd require it to be sound and programs to be total: an infinite loop is a proof of anything, and type system unsoundness leads to false proofs
- ekvintroj 3y agoTry to type a flatMap and then we talk.
- deleted 3y ago[deleted]
- anamexis 3y agotype ValueOrArray<T> = T | Array<ValueOrArray<T>>; type FlatMap<In, Out> = (array: Array<In>, fn: (el: In) => ValueOrArray<Out>) => Array<Out>;
- ekvintroj 3y agoThis does not work, that's the issue, try to run it.
- anamexis 3y agoIt seems to work for me, what issue are you seeing? https://www.typescriptlang.org/play?target=6#code/C4TwDgpgBAaghgGwK4QPICcCC71xAHgBUA+KAXikKgB8ptcD5k0sc8jjiBuAKFEigBZOGABiAO3wBJcQBooqJMFIUAFBAQAuKDICU5UkxQZ67Rcr7hoohHGDCw0uQqUqoquGxDbTBGcXkAM3FtBwkneXNifTJSX3wo3h5ApHEAY2AASwB7cShA22BgCEkSDy8fL3wjFniSaMqGDigAbx4oDqg03IBnYCh0CB6kBGBG9hJyKABtAF12zsDs9Hdu8T6oDShswKhPBn02zuOoTN3VXwA6TJ7fdQRdQ4WTk8Hh0cuwJB6AC1VLgEFOzFcT3R7PE4AX02CB60COL1eQxGwE+3z+Gl0EOOkIhuIhg2ASHQeTeKJ4kKSKXSWVy+UKDgiLmU5QY4z84gC+RCQhE4RkkVcunZCVcrQJECJJPpwJKrLwlwAtiJVMFHrxKTxkqkMjk8jcbHZGQLmcRVTzDfYREyosKoAA3bKZAAmrXxBoZKqBVrAui4QA https://www.typescriptlang.org/play?target=6#code/C4TwDgpgBA...
- klysm 3y agoIs this actually an issue?
- foepys 3y agoI don't get TypeScript's type system. It is obviously very powerful and can model very complex type constraints. But then you have stuff like this where it is not checking types as I would expect: interface Foo { bar: string; } const f = {bar: "foobar"} as Readonly<Foo>; function someFunc(): Foo { return f; // No error or warning, even with all strict flags enabled }
- sakesun 3y agoThis is an issue open for discussion since 2017 https://github.com/microsoft/TypeScript/issues/13347 https://github.com/microsoft/TypeScript/issues/13347
- rendall 3y agoSorry, I don't get it. What do you expect to happen here?
- PhilipRoman 3y agoPresumably the issue is that a Readonly<Foo> shouldn't be a subtype of Foo I should note that I haven't yet had the pleasure of using a language that handles const-ness properly, as Readonly<T> should be neither a subtype nor a supertype of T
- rendall 3y agoAs an aside, I'm on mobile and tried to visit the TypeScript playground to play around with this, but weirdly, the default code is an implementation of FizzBuzz! There was not an obvious way to clear it to get a blank editor. Even "select all" context menu was hijacked. So I gave up. I'll have to file an issue.
- eyelidlessness 3y agoWhat I do is delete all but a few characters after “code” in the URL, then reload to get an empty playground. It’s annoying but it works.
- bottlepalm 3y agoI’m really interested in this for fun, but it’s still way over my head. And this is someone who has been using typescript daily for years. Would love to read something more long form that builds up to this.
- ralphc 3y agoIs it just me or do other people read things like "covariance on a mutable generic type" and just want to get stuff done? Maybe it's because nowadays I do solo or small team projects but this is why I fled to Elixir, it's mostly dynamically typed and you can gradually get into types when you want it, Elixir is cool with that.
- toastal 3y agoCan you? Certainly. Should you? Ehhhhh… The post is experimenting with the type system—which is neat—but before you think you should push this in production (having been in positions to work with heavy-FP’d code), consider an actual FP language if that’s the style you want. The ergonomics are so bad compared to any FP lang→JS option. Currying/partial application, first-class composition/bind/apply, pattern matching not using a ._tag property with a String key, and more are just missing (see: migrating from PureScript/Haskell[0] for fp-ts to see how verbose basic concepts becomes). The other issue is that with TypeScript being multiparadigm and idiomatic TS leaning to imperative/OO due to ergonomics and Java’s legacy on culture/education, there’s a good chance your coworkers/contributors will be expecting a non-FP style which will cause even more friction as you try to justify ‘purity’ to folks that just see a verbose codebase that likely is leaning hard into a lib, quality as it is, like fp-ts which cosplays as Haskell, PureScript, OCaml, Idris, et. al. [0]: https://gcanti.github.io/fp-ts/guides/purescript.html https://gcanti.github.io/fp-ts/guides/purescript.html