Remix.run Logo
LordN00b an hour ago

In the first example you deliberately create an ambiguous type, when you already know that it's not. You told the compiler you know more than it does. The second is a delegate, that will be triggered at any point during runtime. How can the compiler know what x will be?

bspammer an hour ago | parent | next [-]

For the first one, the compiler should not allow the mutable list to be assigned to a more broadly typed mutable list. This is a compile error in kotlin, for example

    val items: MutableList<Int> = mutableListOf(3)
    val brokenItems: MutableList<Any> = items
debugnik an hour ago | parent | prev | next [-]

First example: you're confusing the annotation for a cast, but it isn't; it won't work the other way around. What you're seeing there is array covariance, an unsound (i.e. broken) subtyping rule for mutable arrays. C# has it too but they've got the decency to check it at runtime.

Second example: that's the point. If the compiler can't prove that x will be initalised before the call it should reject the code until you make it x: number|undefined, to force the closure to handle the undefined case.

jstanley an hour ago | parent | prev [-]

If it only works when you write the types correctly with no mistakes, what's the point? I thought the point of all this strong typing stuff was to detect mistakes.

macguillicuddy 5 minutes ago | parent [-]

Because adding types adds constraints across the codebase that detect a broader set of mistakes. It's like saying what's the point of putting seatbelts into a car if they only work when you're wearing them - yes you can use them wrong (perhaps even unknowingly), but the overall benefit is much greater. On balance I find that TypeScript gives me huge benefit.