Remix.run Logo
ForHackernews 13 hours ago

Honestly 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 12 hours ago | parent | next [-]

I 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.

samdoesnothing 5 hours ago | parent | next [-]

You can encode that "correctly" in pure JS

   class LoadingState extends State {}
   class ResultState extends State {}
   class ErrorState extends State {}
   const state: State = new LoadingState
Generally it's a bad pattern to have dependant fields like your example, but you don't need TS to solve it.
what 6 hours ago | parent | prev [-]

>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 5 hours ago | parent [-]

For 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 5 hours ago | parent [-]

Pushing everything to types like this creates a different burden where you're casting between types all over the place just to use the same underlying data. You could just clamp velocity to 200 in the callee and save all that hassle.

kennywinker 4 hours ago | parent [-]

Casting? Not really - i think you’d only need a couple type checks.

Imo this is mostly useful for situations where you want to handle input validation (and errors) in the UI code and this function lives far away from ui code.

Your point about clamping makes sense, and it’s probably worth doing that anyway, but without it being encoded in the type you have to communicate how the function is intended to be used some other way.

samdoesnothing 3 hours ago | parent [-]

How would you convert a Number type to a ClampedNumber type without casting?

kennywinker 2 hours ago | parent [-]

Ah, yeah you’re right. I somehow thought typescript could do type narrowing based on checks - like say:

If (i >= 1) { // i’s type now includes >= 1 }

But that is not the case, so you’d need a single cast to make it work (from number to ClampedNumber<1,200>) or however exactly you’d want to express this.

Tbf having looked more closely into how typescript handles number range types, I don’t think I would ever use them. Not very expressive or clear. I think I hallucinated something closer to what is in this proposal: https://github.com/microsoft/TypeScript/issues/43505

I still think that the general idea of communicating what acceptable input is via the type system is a good one. But the specifics of doing that with numbers isn’t great in typescript yet.

samdoesnothing 2 hours ago | parent [-]

How would you implement it in other languages that support it better? Can you literally just do a range check and the compiler infers its range for types? If so thats actually pretty neat.

IceDane 11 hours ago | parent | prev [-]

Blub.