var/list/Teams = list(list(), list(), list())
...
if (Teams[0].len > Teams[1].len)
The compile errors make this clear enough, that the type of the object at a given index isn't known, so trying to treat Teams[n] as a list won't work.
What I propose is being able to do, for example, this:
var/list/list/Teams = list(list(), list(), list())
...
if (Teams[0].len > Teams[1].len)
var/list/list/Teams. This would be propagated anywhere that Teams[] is referenced, meaning that the if() statement in the second example would work.
Furthermore, something like
var/list/list/mob/Teams = list(list(), list(), list())
/mob/var/IsTeamLeader = 0
...
Teams[0][0].IsTeamLeader = 1
Should be possible, simply by nesting the type path into the list definition. This would work much like existing variable definitions, e.g.
/datum/CustomType/proc/GetDistanceTo(var/datum/CustomType/To)
if (IsAtom(To))
To = new/datum/CustomType(To)
This code example could by passed an atom for example, even though the type says it's not. The same would apply to non-generic lists; the compiler would assume that the object at that index is of a given type and it's up to the developer to either ensure that said assumption is maintained, or handle if it isn't.
If you don't want to first assign the returned value to a variable, you can pass it through a procedure (which is really also just first assigning it to a variable, just with more overhead):
It makes more sense for built-in procs like length(), but I wouldn't suggest actually doing something like getHealth() or setIsTeamLeader()...