In practice, claiming that x$x$ being of type T$T$ *usually* is used to describe *syntax*, while claiming that x$x$ is in set S$S$ is *usually* used to indicate a *semantic* property. I will give some examples to clarify this difference in *usage* of types and sets. For the difference in what types and sets actually *are*, I refer to Andrej Bauer's answer.

## An example

To clarify this distinction, I will use the example given in Herman Geuvers' lecture notes. First, we look at an example of inhabiting a type:

3+(7∗8)5:Nat,$$3+(7\ast 8{)}^{5}:\mathrm{N}\mathrm{a}\mathrm{t},$$

and an example of being member of a set:

3∈{n∈N∣∀x,y,z∈N+(xn+yn≠zn)}$$3\in \{n\in \mathbb{N}\mid \mathrm{\forall}x,y,z\in {\mathbb{N}}^{+}({x}^{n}+{y}^{n}\ne {z}^{n})\}$$

The main difference here is that to test whether the first expression is a natural number, we don't have to compute some semantic meaning, we merely have to 'read off' the fact that all literals are of type Nat and that all operators are closed on the type Nat.

However, for the second example of the set, we have to determine the semantic meaning of the 3$3$ in the context of the set. For this particular set, this is quite hard: the membership of 3$3$ for this set is equivalent to proving Fermat's last theorem! Do note that, as stated in the notes, the distinction between syntax and semantics cannot always be drawn that clearly. (and you might even argue that even *this example* is unclear, as Programmer2134 mentions in the comments)

## Algorithms vs Proofs

To summarize, types are often used for 'simple' claims on the syntax of some expression, such that membership of a type can be checked by an *algorithm*, while to test membership of a set, we would in usually require a *proof*.

To see why this distinction is useful, consider a compiler of a typed programming language. If this compiler has to create a formal proof to 'check types', the compiler is asked to do an almost impossible task (automated theorem proving is, in general, hard). If on the other hand the compiler can simply run an (efficient) algorithm to check the types, then it can realistically perform the task.

## A motivation for a strict(er) interpretation

There are multiple interpretations of the semantic meaning of sets and types. While under the distinction made here extensional types and types with undecidable type-checking (such as those used in NuPRL, as mentioned in the comments) would not be 'types', others are of course free to call them as such (just as free as they are as to call them something else, as long as their definitions fit).

However, we (Herman Geuvers and I), prefer to not throw this interpretation out of the window, for which I (not Herman, although he might agree) have the following motivation:

First of all, the intention of this interpretation isn't *that far* from that of Andrej Bauer. The intention of a syntax is usually to describe how to construct something and having an algorithm to actually construct it is generally useful. Furthermore, the features of a set are usually only needed when we want a semantic description, for which undecidability is allowed.

So, the advantage of our more stricter description is to keep the separation *simpler*, to get a distinction more directly related to common practical usage. This works well, as long as you don't need or want to loosen your usage, as you would for, e.g. NuPRL.