This is working as intended. TypeScript has structural subtyping, which means that a value of type X is assignable to a variable of type Y if every member required in type Y is present in type X.
So all that's needed for a value to be a valid MyInterface is for it to have a myProp1 property of type string. And every instance of MyClass does have such a property (which is why implements MyInterface compiles without error), so according to TypeScript, it's perfectly fine to assign a MyClass instance to a variable of type MyInterface.
It is true that TypeScript sometimes does complain about extra properties, via excess property checking, but this only triggers in certain circumstances; in particular if you assign an object literal with more properties than expected. Since the expressionnew MyClass('1') is not an object literal, there is no warning. This is described as being intentional in microsoft/TypeScript#5303.
Furthermore, the compiler does not keep track of what's been assigned to a variable of a non-union type. The type of instance is the non-union MyInterface type, and so the assignment instance = new MyClass('1') does not change that. It is not narrowed to MyClass, and thus you cannot access the myProp2 property through instance (as MyInterface has no known myProp2 property).
Note that this differs from the behavior on union-typed variables, where assignments will narrow the variable to just those union members with which the assigned value is compatible:
let instance: MyClass | Date = new MyClass('1');
instance.myProp2; // okay
This means that you really don't want to annotate a variable's type with a non-union type unless you want that variable to take on different values of that type and you don't need to keep track of which value it has. If instance will always be an instance of MyClass and that's all you need to know, then you can annotate it as such:
let instance: MyClass = new MyClass('1');
instance.myProp2; // okay
or don't annotate it at all and let the compiler infer its type to be MyClass:
let instance = new MyClass('1');
instance.myProp2; // okay
Generally speaking it's a good idea to let the compiler infer types for you and only annotate things if you need to exert more control than inference gives you.
Playground link to code
MyInterfaceso it is treated as having only the attributes defined inMyInterface. If you don't add the annotation the type will be correctly inferred