Normally, typename is used to disambiguate between cases where an identifier may refer to a type, or may refer to something else:
template
The keyword typename is only permitted by the C++ syntax to introduce a template type parameter, or before a qualified name, i.e. something containing the :: token.
So your #1 and #2 are ill-formed because MyClass and T are unqualified names, not containing any ::.
Before a qualified name, the typename token is:
C++17 [temp.res]/3,5,6:
When a qualified-id is intended to refer to a type that is not a member of the current instantiation and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword
typename, forming a typename-specifier. ...A qualified name used as the name in a class-or-decltype (Clause [class.derived]) or an elaborated-type-specifier is implicitly assumed to name a type, without the use of the
typenamekeyword. In a nested-name-specifier that immediately contains a nested-name-specifier that depends on a template parameter, the identifier or simple-template-id is implicitly assumed to name a type, without the use of thetypenamekeyword. [Note: Thetypenamekeyword is not permitted by the syntax of these constructs. - end note]If, for a given set of template arguments, a specialization of a template is instantiated that refers to a qualified-id that denotes a type or a class template, and the qualified-id refers to a member of an unknown specialization, the qualified-id shall either be prefixed by
typenameor shall be used in a context in which it implicitly names a type as described above.
So your #3 is well-formed, even though the name does not depend on a template parameter and isn't even in a template declaration.
Note C++20 will add many more contexts where typename is optional even with a dependent name, because it's possible to unambiguously determine from the contexts that the name can only mean a type.