I've never really had a problem with it, but I isolate such resources behind a wrapper, which makes cleanup easy. I just create a little higher-order function:
> this drives me absolutely insane (console.log(["10", "10", "10"].map(parseInt) outputs [10, NaN, 2])
That's not really an issue with the type system, that's just coincidence and bad luck.
The signature of parseInt is:
parseInt(string: string, radix?: number | undefined): number
And Array<string>.map(fn) takes a function with the signature:
fn(element: string, index?: number | undefined, array?: string[] | undefined): any
So parseInt coincidentally matches the signature Array<string>.map() is looking for.
I'm not sure what you expect the type system to do here. It works just fine at catching an actual type error, such as this:
console.log([10, 10, 10].map(parseInt)
...which correctly complains:
Argument of type '(string: string, radix?: number | undefined) => number' is not assignable to parameter of type '(value: number, index: number, array: number[]) => number'.
Types of parameters 'string' and 'value' are incompatible.
Type 'number' is not assignable to type 'string'.
(As I'm sure you know, this is the correct code: `console.log(["10", "10", "10"].map(s => parseInt(s))` .)
Map’s second and third parameters are optional. Your functions aren’t required to implement them, which is good, because most of the time you don’t need them.
Again, this isn’t a type system issue. It’s both an API design issue and a poor programming hygiene issue. (Don’t pass bare functions if you don’t know what the parameters are.)
I mean, map always passes them in, so in that sense they aren't optional. Mixing that with functions that take in optional parameters, but aren't usually called with them, gives you a ticking time bomb, IMO. And double that danger when the language's type system allows you to call a function with more parameters than it could ever take.
> Don’t pass bare functions if you don’t know what the parameters are.
This is exactly the kind of thing I want my programming language's type system to catch for me, if I'm working in a language with a static type system like TS.
And even in dynamic languages, this is exactly the kind of thing I want my programming language to catch for me at runtime. Python does, for example.
Stuff like this - while it might fit JS and TS and make sense to some - makes absolutely no sense to me, and is why I simply look to other languages to fit my needs.
How would you change the Type System to fix this particular issue?
>> Don’t pass bare functions if you don’t know what the parameters are.
> This is exactly the kind of thing I want my programming language's type system to catch for me, if I'm working in a language with a static type system like TS.
Hows your compiler supposed to know you don't know what the parameters are?
> How would you change the Type System to fix this particular issue?
In TS you really can't (that's my point and why I prefer to avoid the language) because of JS and API baggage. But just about every other static language that I've worked in can complain for this kind of thing.
> Hows your compiler supposed to know you don't know what the parameters are?
Why does the compiler care about what I know? The compiler itself knows what the function's parameters are and it can tell me that something seems wrong because I'm asking it to call a function that maxes out at 2 parameters with 3 parameters.
TS does catch this kind of thing in a lot of places. It just intentionally decides not to do it for these kinds of callbacks because of the same JS and API baggage.
I've never really had a problem with it, but I isolate such resources behind a wrapper, which makes cleanup easy. I just create a little higher-order function:
> this drives me absolutely insane (console.log(["10", "10", "10"].map(parseInt) outputs [10, NaN, 2])That's not really an issue with the type system, that's just coincidence and bad luck.
The signature of parseInt is:
And Array<string>.map(fn) takes a function with the signature: So parseInt coincidentally matches the signature Array<string>.map() is looking for.I'm not sure what you expect the type system to do here. It works just fine at catching an actual type error, such as this:
...which correctly complains: (As I'm sure you know, this is the correct code: `console.log(["10", "10", "10"].map(s => parseInt(s))` .)