I think there is a lot of useful information, within a function body, that can be created by inclusion of specific types. I don't think your decision was bad. People obviously like the language and the compiler's type inference systems are apparently extremely advanced.

In my opinion this is an anti-pattern for beginning developers and complicates the development of IDEs. This is for a number of reasons.

1. Saving screen space is not a good reason to omit types

Long long ago the people typing away at Bell Labs made these same decisions. All across the UNIX kernel and user space they used partial/shortened names. This did not help users nor did it help developers. K.T. is said to have joked that the missing "e" from "ceat" is his biggest regret from the UNIX system.

We don't use 80x40 terminal displays and most of us type at faster than 25wpm. The space or time saved when writing...

let people = new List<String>();

When compared to...

List<String> people = new List<String>();

Is not worth it in my opinion. This is even more so when you have situations like this

List<String> people = getGuestList();

vs

let people = getGuestList();

In my opinion this is considerably more difficult to understand what type I'm working with. I have to now go and read the header for `getGuestList()` to find out what I can do with my `people` variable.

2. IDE development will be more difficult.

This is minor, and will eventually be a solved problem, but writing an IDE that doesn't have immediate type information for everything in scope will be more complicated. Some may even say this might be impossible to accomplish via static analysis. Because of this the development of things like the RLS are much more difficult.

3. The seasoned but new developer will struggle to find how things work.

When I pick up a new programming language at this stage in my career I no longer read through a book or documentation. I sit down and I try and accomplish a project. I find a task, find some code that does the subsets of the problems I want to solve, read that code, then implement my own solutions with the knowledge that I've gained. With Rust this approach doesn't work (for me). I have not been able to pick up Rust. I don't know what kind of objects are being used to hold which kind of data without reading almost every single line of code in the program (or at least everything accessible from the scope I am interested in).

In Java, C, etc I get some clue as to what's going on. In Java I need to only read maybe the first few words on every line to get an idea of what will happen or what is being used.

public boolean isOnGuestList(String person) {
List<String> people = ...;
List<String> plusOnes = ...;
return people.contains(person) || plusOnes.contains(person);
}

I might not know what a List<String> is but I can easily find out.

This biggest effect this has is that since I have been programming for a long time I have an intuition where certain language features will be used. Every* language has a KV store, a list, some way to interact with file descriptors, etc. I know what kinds of programs will do those things and I can look at those programs for reference. Unfortunately for languages like Rust I need to already know the general types that people use to understand the code. All I would see is...

fn isOnGuestList(person: string) -> string {
let people = ...;
let plusOnes = ...;
people.contains(person) || plusOnes.contains(person);
}