Posted by ocamoss 4 days ago
In Python, `x = []` should always have a `list[…]` type inferred. In TypeScript and Ruby, the inferred type needs to account for the fact that `x` is valid to pass to a function which takes the empty tuple (empty array literal type) as well as a function that takes an array. So the Python strategy #1 in the article of defaulting to `list[Any]` does not work because it rejects passing `[]` to a function declared as taking `[]`.
I'm a bit confused by the fact that the array starts out typed as `any[]` (e.g. if you hover over the declaration) but then, later on, the type gets refined to `(string | number)[]`. IMO it would be nicer if the declaration already showed the inferred type on hover.
I think one reason might be to allow the type to be refined differently in different code paths. For example:
function x () {
let arr = []
if (Math.random() < 0.5) {
arr.push(0)
return arr
} else {
arr.push('0')
return arr
}
}
In each branch, arr is typed as number[] and string[], respectively, and x's return type is number[] | string[]. If it decided to retroactively infer the type of arr at declaration, then I'd imagine x's return type would be the less specific (number | string)[].https://www.typescriptlang.org/play/?#code/GYVwdgxgLglg9mABM...
`unknown[]` might be more appropriate as a default, but TypeScript does you one better: with OP's settings, although it's typed as `any[]`, it'll error out if you don't do anything to give it more information because of `noImplicitAny`.
I don't enable strict mode on multiple projects because people don't want to type anything outside of function signatures.
Inferring the type from the first use is 100% the correct choice because this is what users want 99% of the time, for the rest you can provide type information.
Can you elaborate on that?
Prior to 2.3 Python didn't have booleans, just "truthiness". In 2.3 they added the Boolean class as a subclass of int (because of patterns of development it was a pragmatic choice). True and False were introduced, but they were able to be reassigned which could cause all manner of fun. 3.x made them keywords which put a stop to that but the int aspect remained.
So, can we add two bools together? Adding booleans together is nonsense, but we've said these are a kind of integer so sure, I guess True + True = 2 ? And this cascades into nonsense like ~True being a valid operation in Python and its result is true...
>>> isinstance(False, int)
True
A related screw-up is implicitly casting everything to bool. A lot of languages made that mistake.Overall I'd say they didn't do an awful job though. The main problems with Python are the absolutely abysmal tooling (which thankfully uv fixes), the abysmal performance (which sometimes isn't an issue, but it usually becomes an issue eventually), and the community's attitude to type checking.
Actually type checking code you've written yourself with Pyright in strict mode is quite a pleasant experience. But woe betide you if you want to import any third party libraries. There's at least a 50% chance they have no type annotations at all, and often it's deliberate. Typescript used to have a similar problem but the Javascript community realised a lot quicker than the Python community that type hints are a no-brainer.
If you ignore the bit where they don't actually specify their semantics anyway.
> this can't be the way..
The alternative is fragile and unmaintainable code. I know which I prefer!