Personally, I hate the latter, but not as much as I hate unsoundness.
But, what I'm talking about is even more basic: https://www.typescriptlang.org/play?#code/MYGwhgzhAECCB2BLAt...
The code I wrote there is actually wrong for two reasons:
1. Type variance
2. Readonly doesn't do fuck-all in TypeScript for object types
I guess my point was more about the reasons behind these weird rules. AFAIK interop with existing JavaScript was not the primary reason for doing them this way, if that's any consolation.
FWIW your example wouldn't fly in Flow
https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVBjGBDAzrsAQQDsBL...
Are you sure? Because there was an essay written by the TypeScript devs when they released whatever version that introduced the strict-function-variance flag explaining why they "couldn't" make it also apply to class methods, and it boiled down to breaking too much existing JavaScript code.
That's not proof that the original variance choice was also due to JavaScript compatibility, but I feel like it's a very strong suggestion that it was probably a big motivator.
I'm glad that it wouldn't work in Flow. I'm sure it wouldn't work in most/all of the other statically typed compile-to-JavaScript languages. I just hate that none of them won out over TypeScript, so they're basically all irrelevant- Flow included.
FWIW the lack of explicit variance annotations (and probably many other TS unsound design choices) are not so much related to supporting old untyped JS, but rather language design decisions that have to do with pragmatism and type system complexity.
I can't find it now but I have a vague recollection Hejlsberg talking about the explcit variance annotations explicitly, how those were a huge can of worms in C# and they didn't want to bring them to TS. Unlike Flow, by the way, which does have explicit variance handling and doesn't suffer from the beforementioned foot gun (but does have its own foot guns of course).