type x = y does the same that x: typing.TypeAlias = y used to do. It basically is just syntactic shugar for that, allowing us to define TypeAliases more easily.
For the interpreter these two things are completely different since type aliases are lazily evaluated references to the type, which fits in the PEP 649 world, where annotations are lazily evaluated, unlike strings as under from __future__ import annotations.
The two mechanisms work similarly, but are largely unrelated. Even if PEP 649 had been implemented first, the assignment version a: TypeAlias = b would not have been evaluated lazily. From the interpreter’s point of view, that really is just a bog standard assignment statement. There’s no kind of code transform, special casing, or really anything like that going on there. It’s the exact same as e.g. writing a = 123 and just assigns b to a. But type a = b doesn’t do that. It creates a TypeAliasType object with a specially synthesized set of methods and assigns that to a.
Yeah, I rather talked about the perspective of type checkers though (which seems to not have been as clear as it should be). I suppose type checkers also evaluate types (e.g. forwardrefs) lazily, at least since PEP 649.
At runtime the meaning of a keyword obviously is different to that of a Type-hint (which is ignored anyways).
But to get back to topic, type x is, as far as I know, a type statement in all cases, even though it can be used at runtime like a normal object (although it is of type TypeAliasType).