Types are what a thing is. For example, some languages have a general Number type. Some distinguish between whole numbers and decimal numbers, "ints" and "floats" respectively (most of the time, they're called that). Some go even further and define a Fraction type, or a Complex type, or what have you.

This is just a simple example. You might have a Point type, that has an "x" field and a "y" field, each floats (decimals). You can define your own types! The whole idea behind a strongly-typed, statically-typed system like we're talking about here, is that every value you store, manipulate, or pass around has a definition. When you call a function that returns a Point, it returns a Point, dammit! Well, unless it's an optional value – then it might be empty. But still! The point is, you know what you're getting. It does what it says on the tin.

Willy Wonka's flavored wallpaper was clearly statically typed.

The problem with static typing is you have to define all this stuff that is very probably going to change a lot early on. Statically typed languages are famously inferior to dynamically typed languages in this regard: speed of prototyping.

But what if we could have our cake and eat it too?

Let's imagine we have a source file, that contains our lovely, untyped, prototype code. We just wrote it, haven't even run it through the compiler to turn it into a program.

When we run the compiler, what if it generated type definitions? That would be cool, right?

On the first run, you could see each data type being passed into a given function, and determine what the types need to be down to the primitive (string / number / etc.) values that make up a composite object, and you could give a temporary name to the composite object (say ${functionName}ParameterList or some such).

Nested objects would have nested types. You'd determine the composition of every composite value, and amend the source code file to include the type annotations, like little notes to the developer saying "hey, this is a FoobarParameterList, and this is how it's shaped".

If the developer changes the name of the type, the name is changed in the definition file. Likewise, if the usage of that type changes, the definition changes!

If you have conflicting usage, the compiler warns you. If everything is in harmony, though, you get all of the "statically" typed goodness with the feel of a dynamic language.

Combined with type inference like Rust has, we can get close to an ideal system.

Or maybe I should just make you define your own types! What am I, Houdini?

Eh, we'll see. For now, with what is now apparently a traditional sign off, a song for you:

A wizard has no type