Live data from Hacker News

Learn how to unleash the full potential of the type system of TypeScript

type-level-typescript.com

181–190 of 256 posts

Re: Learn how to unleash the full potential of the type system of TypeScript

#181

Earlier quoted context omitted.

You'll export a function from your esModule if you want to inject export const myFn = (...deps) => You don't need anything else, for encapsulation you have the EsModule, that what OP meant.

ah, thanks, I thought it was something different.

You have dynamic imports too if you need IoC.

Re: Learn how to unleash the full potential of the type system of TypeScript

#182

Earlier quoted context omitted.

Yeah, what a terrible syntax :( Just today I was looking at the type definition for a third-party lib (ramda)... what the heck does this even mean... compose (fn5: (x: T5) => T6, fn4: (x: T4) => T5, fn3: (x: T3) => T4, fn2: (x: T2) => T3, fn1: (x: T1) => T2, fn0: (x0: V0, x1: V1, x2: V2) => T1): (x0: V0, x1: V1, x2: V2) => T6; Got it?

compose is a higher order function. In the first step it accepts a function that converts 3 values (V1 to V3) into a single values (T1) and a series of conversion functions that converts this single value into another value (T1 into T2, T2 into T3 and so on until T6). Using these functions it produces a new function that converts the combination of V1, V2 and V3 into a T6. I don't know ramda, but I assume this is onl…

Great and simple explanation. Suddenly it doesn't feel cryptic, simply logical. Thx!

Re: Learn how to unleash the full potential of the type system of TypeScript

#183

Earlier quoted context omitted.

> I think that this signature is pretty clear for anyone experienced with a statically typed language with generics and higher order functions. Sounds like I have stuff to study! Maybe ramda was an extreme example (with or without typescript, it was so hard to read that our dev team decided to just remove it altogether and replace it with more verbose but easier to read vanillaJS code or equivalent lodash functions).…

From what you are writing, you really lack the basics here. Learning on the job is fine, but sometimes it's worth to spent dedicated time to learn foundations or at least get someone on board who can teach them. I suggest to try to get your boss to sponsor this, since you need it for the job. It will also make your dev experience so much more fun!

For sure. I am no TypeScript expert, and for the most part I don't really need to be... most of our types are pretty straightforward, arrays of strings and such.

Learning is great, but this job, like many others, doesn't really have a well-defined system for training, documentation, professional development, or anything like that. Either I learn on the job as it happens or I don't learn at all. There's always too much to build, with constantly shifting priorities defined and redefined by higher-ups who don't know or care what TypeScript is. Sure, I can push back on that to some degree and beg for a resource or two, but even that is difficult, and there's always so much else that's even more pressing to learn. And web dev by its nature is a broad and shallow career anyway, especially on the frontend... by the time you begin to master something, it's already obsolete lol.

TypeScript looks like it'll have some staying power, so I'm happy to learn it as I go. But over time, I've learned to stop chasing perfection and to just go for "Will this survive long enough until the rewrite in a year or two? If so, good enough...". I've never known a job like this where code survives longer than 2 or 3 years before someone, either a dev or a manager, wants to rewrite it from scratch.

A lot of our existing codebase was written by contractors who had a lot of experience, but little desire to document anything or comment anywhere. Our current generation of (relatively junior) devs inherited that, has trouble with a lot of it, and ends up rewriting large overengineered swaths in simpler patterns as we go. A complete rewrite is already planned. And so the cycle continues :)

In general, the barrier to entry for JS/web dev is pretty low, and so there are a lot of low-to-med skilled devs like me in the industry. I think, philosophically, I lean against writing code that is overly "clever" rather than readable. Similarly with types. If a typing becomes complex enough that it's not really readable, I'd rather just leave a clear comment as to what the intent is and then move on, knowing that the code itself -- much less its typing -- is unlikely to survive long anyway. At the end of the day, IMO, it doesn't make sense to have types that are more complicated than the code itself... if correctness is important but the typing is complicated, I try to break down the code itself, add comments, add unit tests, add documentation, etc. rather than try to coerce TypeScript into sentience.

Is that the most "correct" way? Probably not. But it sure makes things easier to read in PRs rather than telling everyone, "Well, you need to learn advanced TypeScript if you want to read my contribs."

Re: Learn how to unleash the full potential of the type system of TypeScript

#184

> Over the years, the type system of TypeScript has grown from basic type annotations to a large and complex programming language. Give someone (particularly a developer) the opportunity to build something complicated and undoubtedly they will. So now you have two problems, the complicated program that actually does some hopefully useful work, and another complicated program on top of it that fills your head and slow…

> Almost all bugs are logic bugs or inconsistent state bugs (thanks OOP!), almost none are type bugs.

What if you drastically reduce the possibility of inconsistent state by making it unrepresentable at the type level?

What if you immediately know that you’ve exhaustively handled all your cases?

What if types push parsing in the right direction?

Re: Learn how to unleash the full potential of the type system of TypeScript

#185
post #75

A great idea. Now, everyone that learns this stuff, show some restraint! The drawback of a powerful type system is you can very easily get yourself into a type complexity mudhole. Nothing worse than trying to call a method where a simple `Foo` object would do but instead you've defined 60 character definition of `Foo` capabilities in the type system in the method signature. Less is more.

This is so true. I've been thinking recently that in the same way that "use boring technology" is a pretty well-known concept, so should "use boring types" enter the collective conscious. Type operators are exciting and flashy, but I found that using them too much leads to brittle and confusing types. Saving them for a last resort tends to be the right strategy. Often there's an extremely dumb way to write your types…

If you only use "simple types" then you often get implicit assumptions about the "values". For instance note that "web-services" basically means you have a very simple interface defined by the HTTP-protocol.

But what is actually inside the HTTP-payloads can then have many constraints on them which are not declared anywhere. For instance your code might assume the payload is JSON with several required fields in it.

Re: Learn how to unleash the full potential of the type system of TypeScript

#186
post #41

Is there any place I could report issues or ask questions about the course other than Twitter? If the author is reading this, the proposed solution to the `merge` challenge is: function merge (a: A, b: B): A & B { return { ...a, ...b }; } That's the "obvious" solution, but it means that the following type-checks: const a: number = 1; const b: number = 2; const c: number = merge(a, b); That's not good. It shouldn't ty…

> And I don't know how to express the correct solution (i.e. where we actually assert that A and B are object types). You can do this: function merge , B extends Record >(a: A, b: B): A & B { return { ...a, ...b } } const result = merge({ a: 1 }, { b: 2 })

This fails on:

  const result = merge({ a: 1 }, { a: "fdsfsd" })
The correct type is quite complex and depends on whether or not `exactOptionalPropertyTypes` is enabled.

EDIT: I think this is correct for when `exactOptionalPropertyTypes` is off.

  type OptionalKeys = { [K in keyof T]: {} extends Pick ? K : never }[keyof T]

  function merge(a: A, b: B): {
    [K in Exclude]: B[K]
    } & {
      [K in Exclude]: A[K]
    } & {
      [K in keyof A & keyof B]: K extends OptionalKeys ? A[K] | Exclude : B[K];
    }
That's for when `exactOptionPropertyTypes` is enabled. With it disabled, then you'd replace `Exclude` with `B[K]`.

As to whether this is a good idea. Ah... it's not :P

Re: Learn how to unleash the full potential of the type system of TypeScript

#187

> Over the years, the type system of TypeScript has grown from basic type annotations to a large and complex programming language. Give someone (particularly a developer) the opportunity to build something complicated and undoubtedly they will. So now you have two problems, the complicated program that actually does some hopefully useful work, and another complicated program on top of it that fills your head and slow…

A simple trick with plain JavaScript is to give all arguments default values. That gives a pretty good insight for anybody reading the code as to what "type" of arguments the function expects.

If you test-call such a function without arguments you will then know what kinds of values you can expect it to return.

The argument default values can not be inner functions but they can be any function that is in scope. Or if you are using classes it could a reference to any method of 'this'.

Then add some asserts inside the function to express how the result relates to the arguments. No complicated higher-order type-definitions needed to basically make it clear what you can expect from a function. Add a comment to make it even clearer.

Re: Learn how to unleash the full potential of the type system of TypeScript

#188
post #172

Earlier quoted context omitted.

The thing with electrical plus is that they should be designed around safety first, rather than convenience. And the U.K. plug is a lot more safety focused than many other plug standards. The advantage of the U.K. plug is that live pins are physically blocked and only released when the Earth pin is present. This is why the Earth pin is slightly longer on U.K. plugs and why insulated devices have a plastic Earth pin r…

I don't think the discussion really was about plugs.

Originally, no. But discussions evolved

Re: Learn how to unleash the full potential of the type system of TypeScript

#189

A great idea. Now, everyone that learns this stuff, show some restraint! The drawback of a powerful type system is you can very easily get yourself into a type complexity mudhole. Nothing worse than trying to call a method where a simple `Foo` object would do but instead you've defined 60 character definition of `Foo` capabilities in the type system in the method signature. Less is more.

"Duplication is better than the wrong abstraction"

This is where a lot of developers go overboard - not just in type systems, but in general. They are so afraid of duplication, they over-generalize and end up in a quagmire of unreadable overly complicated code.

Some duplication is easy. It's just code volume, and volume shouldn't be as scary as complexity.

Re: Learn how to unleash the full potential of the type system of TypeScript

#190

Might as well ask here. On our teams, we have the occasional developer that is insistent on using Typescript in an OO fashion. This has always struck me as square peg round hole. Even though I come from an OO background, Typescript strict settings really seem to push me in a direction of using interfaces and types for type signatures, and almost never classes, subclasses, instantiated objects. I don't have a very goo…

I think the word "interface" means something conceptually different in different languages.

in Java it means "you should implement this contract"

in Typescript it means "this data type has this particular shape. It may have methods, too".

in Go it means "I'd like users of this code to implement these methods" (client interfaces).

In all cases you have to work differently with them. It's not even about OOP, I think, to the point where I'm not sure now if the keyword 'interface' is part of OOP at all.

Post reply on HN