When passed as this outside of strict mode, you have the very rare case that you encounter a primitive in their wrapped object form ("boxed"), as instance of String:

You can therefore check if your method was called on a string using this instanceof String instead of typeof this === 'string'. If you want to differentiate between strings and objects that inherit from String, you could use this.constructor === String instead.
To get a "regular" string back (or number for Number, or boolean from Boolean, etc.), you can call this.valueOf()
(This means you could also write typeof this.valueOf() - but note that this may be misleading because any object could return, say, a string from its valueOf method without actually having been a string originally.)
Note: You cannot differentiate between 'abc'.yourMethod() and new String('abc').yourMethod() this way because you get an instance of String either way.
(Also interesting: Seems like for newer types like BigInt or Symbol you cannot manually create such a wrapper instance, new BigInt(1n) will fail. But (function () { return this }).call(1n) would achieve the same, although I have no idea why anybody would want that...)
All that said: The easiest way to get the exact behavior you want (this being the actual string) is by defining your function in a context that is in strict mode:
(function {
'use strict'
Object.prototype.logType = function () { console.log(typeof this); }
})()
Now it will work as intended.