It's nearly impossible for the code, as given, to produce the desired results. When you do console.log(foo), for that to result in 'value' (and only 'value') being logged, foo can only contain the exact string 'value'. It can't even be 'value' wrapped in a String (or custom String) object.
console.log(new String('value'));
 
 
console.log, if passed a single variable, will log exactly what that variable passed to it is. If the variable is an object, it'll log that object, not anything else (like a string or a number). If the variable is a plain string or a number, then it won't have other methods on it, unless you mutate String.prototype or Number.prototype, which you should not do.
The best you can probably achieve would be to have an instance which, when coerced to a string, returns the desired stringified value:
class CustomType {
  constructor(item) {
    this.item = item;
  }
  toString() {
    return this.item;
  }
  method() {
    console.log('doing something');
  }
}
const foo = new CustomType('value')
console.log(foo) // CustomType {item: "value"}  - look in browser console, not snippet
console.log(foo + 'hello') // 'valuehello'
foo.method() // Do something
 
 
I said nearly impossible, not absolutely impossible. If you mutate the prototype of the passed object, you can put method on it to make foo.method() work:
const addCustomMethod = (item) => {
  Object.getPrototypeOf(item).method = () => {
    console.log('doing something');
  };
};
const foo = 'value';
addCustomMethod(foo);
console.log(foo) // 'value'
console.log(foo + 'hello') // 'valuehello'
foo.method() // Do something
 
 
But mutating built-in prototypes is a horrible idea. The above snippet is for informational purposes only, please do not use it.