-1

I want to make an extension method so I can easily print out any typescript primitive or object in human-readable form. So instead of doing JSON.stringify(thing) I can do thing.printNice()

Is this possible? I tried this but it doesn't work:

interface any {
    printNice(): string
}

any.prototype.printNice = function() {
    return JSON.stringify(this)
}

Edit: I see now that this has been asked and the answer is no, you can't. Is there any way to accomplish what I am trying to do? Typing JSON.stringify(thing) all over the place is annoying.

PhillyTheThrilly
  • 1,562
  • 2
  • 16
  • 21
  • I don't think it's possible. any, boolean, number... are not objects, they are types. Types do not have a prototype attribute. I think there's no hack to build an extension method in this case. – julianobrasil Apr 08 '20 at 02:03
  • `any` is a _type_: there's no such `any.prototype` object to add a method to. I see you want it to be like Go's Receiver functions or something, but that's not a thing in TypeScript. – msanford Apr 08 '20 at 02:03
  • 1
    "so I can easily print out any typescript primitive or object in human-readable form" --- you don't need a method for that, just a function is enough. – zerkms Apr 08 '20 at 02:07
  • 1
    Also, with respect, the assertion "Typing JSON.stringify(thing) all over the place is annoying" is a problem of _your IDE_: get one autocompletes with intellisense rather than polluting global Object prototypes. – msanford Apr 08 '20 at 02:09
  • @msanford I'm using VS code. What usually happens is I print a bunch of variables with `console.log` and forget to stringify it, then go back and wrap the variables in `JSON.stringify`. You're right, a better solution would be to be have a macro or something where I can highlight it and auto stringify – PhillyTheThrilly Apr 08 '20 at 03:59

3 Answers3

1

I'm afraid you can't. any is not a class or an interface. It's a construct (type technically) for lack of other words. same as var (as a type not the keyword) or an anonymous object. it's what you want it to be, so it cannot be extended

https://www.typescriptlang.org/docs/handbook/basic-types.html#any

Segev -CJ- Shmueli
  • 1,535
  • 14
  • 15
1

It's possible - nearly everything inherits from Object.prototype, so you can put the method on Object.prototype:

Object.prototype.printNice = function() {
  console.log(JSON.stringify(this));
};

(5).printNice();
({ foo: 'bar' }).printNice();

In Typescript syntax:

declare global {
    interface Object {
        printNice: () => void;
    }
}
Object.prototype.printNice = function () {
    console.log(JSON.stringify(this));
};

(5).printNice();
({ foo: 'bar' }).printNice();

But this is probably not a good idea, because objects do not expect to have a printNice property. Mutating the built-in objects can easily create problems.

Note that objects which do not inherit from Object.prototype won't have the method in their prototype chain:

Object.prototype.printNice = function() {
  console.log(JSON.stringify(this));
};

const someObj = Object.create(null);
someObj.foo = 'bar';
// Error, property does not exist:
someObj.printNice();

(but almost all objects, including primitive wrappers, do inherit from Object.prototype)

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
1

You can extend Object instead.

Object.prototype.printNice = function() {
    return JSON.stringify(this)
}

And then:

function myFunc() {
  return 42;
}
console.log(myFunc.printNice());
sportzpikachu
  • 831
  • 5
  • 18