5 ms·
Even with strict flags on, there are failures. A trivial example: function mutateArray( arr: (string | number)[] ) { arr.push(1); } const a: st
by sargunv 5mo ago
Even with strict flags on, there are failures. A trivial example:
function mutateArray(
arr: (string | number)[]
) {
arr.push(1);
}
const a: string[] = ["one", "two"];
mutateArray(a);
a is now a string[] with a number inside
- teaearlgraycold 5mo agoVery interesting. I’m shocked the typescript creators built a system with this failure mode. I guess the solution here is to have tsc change the type of “a” after the call to mutateArray, unless the arr argument is marked as readonly. Is there a name for this failure mode?
- sargunv 5mo agoI'm not aware of a name, but I'm also curious if there is one because I had a hard time searching for it. I came across it on ThePrimeagen's YouTube channel: https://youtu.be/u1WmiqlrqL0 https://youtu.be/u1WmiqlrqL0
- teaearlgraycold 5mo agoI asked an LLM and it described the problem as "covariant typing of mutable collections" or "unsound covariance". I'm not mathematically educated in this area but that sounds right?
- saghm 5mo agoYes, that's correct. If you're curious for a slightly more concrete source, Wikipedia covers this reasonably well (although citing one often decried source to validate another might not be particularly convincing to some people): https://en.wikipedia.org/wiki/Type_variance#Arrays https://en.wikipedia.org/wiki/Type_variance#Arrays
- sally_glance 5mo agoI think the problem is the union argument type - intuitively we read "array of strings OR numbers", but actually it means "array of strings AND numbers". Probably generics would be more appropriate here, with the type param constrained to string or number. Then tsc would also complain about pushing a number without checking the item type before.
- fainpul 5mo agoIf it's an "array of strings AND numbers", then it should not be allowed to call the function with a string[], because those are different types.
- clownstrikelol 5mo agoThat’s barely scratching the surface. In TypeScript the following is also valid: class Something{ value: Number } class SomethingElse{ value: Number foo: String bar: SomeOtherThing[] } function AddSomething(v: Something) { v.value += 1; } var ex = new SomethingElse{ value: 3, foo: “TypeScript is fake types”, bar: [] }; AddSomething(ex); Why does it work? Because in TypeScript as long as you have a “shape” that fits, it’s the “same type.” Complete and utter insanity to me, to pretend there’s any real type checking, when types are entirely fake and made up.
- saghm 5mo agoThat's because it's structurally typed (as opposed to nominally typed). I don't happen to prefer it, but I don't think it's fair to conflate that with unsoundness like the example given above; it's totally possible to have a sound structural type system. TypeScript doesn't happen to be sound, but it's not because of that.
- teaearlgraycold 5mo agoStructural typing is great. It's the verified version of duck typing.
- deleted 5mo ago[deleted]
- rav 5mo agoIn TypeScript it's called "bivariance", which sounds very programming language theory like, but is not a term typically used in academic contexts, since it is unsound almost by default. It's described here: https://www.typescriptlang.org/docs/handbook/type-compatibility.html#function-parameter-bivariance https://www.typescriptlang.org/docs/handbook/type-compatibil...
- drzaiusx11 5mo agoKey sentence in their justification seems to be: "allowing this enables many common JavaScript patterns" Honestly at this point they should make a new strict "no js" mode, as the ecosystem likely has reached a tipping point where you can get by without mixing typed and untyped js at compile time. Wonder if targeting wasm directly would help ensure those boundaries are ensured...
- drzaiusx11 5mo agohttps://www.assemblyscript.org/ https://www.assemblyscript.org/ is pretty darn close, but it would probably be better to converge and not split communities
- deleted 5mo ago[deleted]
- drzaiusx11 5mo agoYikes. I've only been using ts for about a year, I had no idea this was considered a "valid" case. Seems like a type error to me. I wonder how they justify this?
- stratos123 5mo agoWoah, that's quite an issue. The equivalent code in Python doesn't typecheck, since `list` is invariant and hence list[str] doesn't fit list[str|int]. Unusual for TS to handle types worse than Python.