> You flipped from looking for mutable to immutable and somewhat lost me.
If you want to write a function that takes immutable collections and does not accept mutable ones, that's generally impossible to do in a language with only structural typing. In a language like C# with nominal typing, you can have that function accept an interface that only immutable collection types implement, such as IImmutableList.
> How about we talk about the examples in the article. Stream and StreamReader?
I have no idea what they do or what they're meant for. It's certainly possible to define bad interfaces, I don't think anyone's denying that.
> You can extend those types but you can't apply new interfaces to the existing types.
Sure, that's a limitation and there are various ways to navigate that tradeoff (e.g. adapters, or a Haskell/Rust-style trait system where you can apply interfaces to existing types but you have to do so explicitly). My point is that structural typing is not a flawless approach that solves all your problems.