Something that comes up sometimes in programming languages is the difference between nominal and structural type systems. While I'm definitely not the first to talk about this, something that is remarkable to me is that, in my opinion, this is something nearly every programming language gets wrong.
If you're coming from a language like Java, Kotlin, Haskell, OCaml or Rust (or most other languages really), nominal types are what you would probably just think of as "types".
In a language like this, a type needs to be defined in a type declaration where it is given a name that acts as its sole source of identity, without any regard for its implementation. Even if two separate types happen to share the same implementation, they are deemed unequal because they have different names.
a function accepting an A will not accept a B, because even though their implementations are entirely identical, A and B are not the same type.