Giter Site home page Giter Site logo

Comments (12)

rezonant avatar rezonant commented on June 7, 2024 1

The rule that nothing should be added to Object's prototype is gone IMHO. That was before option enumerable: false. Is there any reason which is it still true?

No, it's still not a good idea to add public methods to the Object or any builtin prototypes. https://developers.google.com/web/updates/2018/03/smooshgate

Besides, how do I get the type of this class?

class Foo {
    _type = 123;
    getType() { return this._type; }
}

Can I expect(new Foo().getType()).to.be.a.number ?
If so then is the way to do it Object.prototype.getType.call(new Foo()) ?

from tst-reflect.

Hookyns avatar Hookyns commented on June 7, 2024 1

But okay, there will be base variant getType(val: any): Type and config option reflection.usePrototype: boolean = false.
That's fair. ๐Ÿ˜‰

from tst-reflect.

rezonant avatar rezonant commented on June 7, 2024 1

A smaller point: Imagine there are two projects that do the same thing. Someone else (maybe making a serialization library or something) also decides to put getType() onto the Object prototype. What happens for users? Why is your getType() "more canonical" than someone else's getType()? What if you want to use those two libraries together?

More importantly though, imagine your project becomes popular out on the web and then WHATWG decides to add a builtin getType() to Object, but they can't because you modified the prototype and shipping that change in the browser will break all of these websites. This is literally what smooshgate was about (Mootools added Array.flatten, became popular, is now out there on websites that will never change, which forced the browser makers to go with Array.flat which is less than the ideal name for the method because Mootools decided they could just monkey patch any extra functionality they had directly onto the builtins). That's what the article above is talking about- and it is a cautionary tale to framework designers in the ecosystem.

Monkeypatching methods onto built in types is short-sighted, will always be frowned upon, and has the real potential to cause problems for the ecosystem if your solution becomes popular. There's so many other good options that bypass this entire problem too, it could be Type.getType(value) or getType(value) (as opposed to getType<T>()) or even getTypeFromValue(value).

I also have a lot of experience in C#, hell I've even implemented portions of the CLR in another life, it's a great language and a great runtime. But what makes C# and the CLR great isn't just that it has a convenient getType() method on the Object class.

It was bad practice because direct Object.prototype.getType change behavior of for..in, that's why x.hasOwnProperty() should be used.

That's a small (but important) detail at the time, but that is a very small reason compared to the larger reason of leaving the namespace on the builtin prototypes free for Ecmascript to define. You might ask, why don't they just disable the ability to modify the builtin prototypes? That would preclude polyfills on already-standardized but not yet implemented features in the JS environment you are running in. It would also preclude Zone.js' patching. And of course it would also break all the websites out there that already did it and that's not really an option. But just because the option is there and the community has made this mistake before (again and again and again) does not mean we should walk carelessly into making that mistake yet again.

Here's just a few references:

from tst-reflect.

Hookyns avatar Hookyns commented on June 7, 2024 1

Done. Without extension of Object's prototype.

@reflect() decorator needed just to say the transformer to include that type into metadata. It will not be needed after "include/exclude" configuration.

@reflect()
class A
{
}

@reflect()
class B
{
}
const a: any = new A();

const typeOfVarA = getType(a);
console.log(typeOfVarA.name); // > "A"

const typeOfA = getType<A>();
console.log(typeOfA.name, typeOfVarA.is(typeOfA), typeOfVarA == typeOfA); // > "A", true, true
const array: any = [new A(), new B()];

const typeOfArray = getType(array);
console.log(typeOfArray.isArray()); // > true

const arrayTypeArg = typeOfArray.getTypeArguments()[0];
console.log(arrayTypeArg.union); // > true
console.log(arrayTypeArg.types.map(arg => arg.name).join(", ")); // > "A, B"
const array2: any = [new A(), new B(), "string", true, false, { foo: "bar"}];

const typeOfArray2 = getType(array2);
console.log(typeOfArray2.isArray()); // > true

const arrayTypeArg2 = typeOfArray2.getTypeArguments()[0];
console.log(arrayTypeArg2.union); // > true
console.log(arrayTypeArg2.types.map(arg => arg.name).join(", ")); // > "A, B, string, boolean, Object"

console.log(arrayTypeArg2.types[4].getProperties().map(p => p.name + ":" + p.type.name)); // > [ "foo:string" ]

from tst-reflect.

rezonant avatar rezonant commented on June 7, 2024

Shouldn't add custom methods to Object prototype, why not use getType(value), just look for the type params in the CallExpression within the transformer and only transform it if it has them

from tst-reflect.

Hookyns avatar Hookyns commented on June 7, 2024

@rezonant
The rule that nothing should be added to Object's prototype is gone IMHO. That was before option enumerable: false. Is there any reason which is it still true?

My reason for that is similarity with C# reflection, and I like OOP more than functional programing.
function getType() {} is here like operator typeof(). TS syntax does not allow anything like that, so it must be function like that.

I think @iDevelopThings want getType() on Object prototype too, right?
We've already discussed this earlier, but I think we've met some troubles,.. I don't remember..

from tst-reflect.

Hookyns avatar Hookyns commented on June 7, 2024

It is the same like .toString().

It is on the prototype, it's default implementation and you override it by your own declaration in your class.

So result of that expect is true.

from tst-reflect.

Hookyns avatar Hookyns commented on June 7, 2024

And yeah.. if you override it, you override it.. your decision... and the only way is to use direct prototype call as you mentioned.

from tst-reflect.

Hookyns avatar Hookyns commented on June 7, 2024

@rezonant why thumb down? I say ok, use getType(value) as you proposed. And my original Object.prototype.getType will be optional, disabled by default.

from tst-reflect.

rezonant avatar rezonant commented on June 7, 2024

Because I think modifying Object prototype even optionally isn't a good idea. You seemed to be pretty decided on it though and if that's what you want to do, well okay.

from tst-reflect.

Hookyns avatar Hookyns commented on June 7, 2024

I'm open to discussion. Tell me why it is not good idea.

There is a history of extending Object's prototype and it was bad practice, but it was a long time ago,.. That time of ES3..
It was bad practice because direct Object.prototype.getType change behavior of for..in, that's why x.hasOwnProperty() should be used. That's why everybody was saying "No! Never! Never extend Object's prototype". Today a lot of people still say that, but they don't know why. They've read some article from 2010 which said it is a bad practice.
But Object.defineProperty() with enumerable: false doesn't do that so I don't know what's the problem. Am I missing something (are there still some problems with that?) or is it just your feeling?

from tst-reflect.

Hookyns avatar Hookyns commented on June 7, 2024

Available from:

[email protected]
[email protected]

Version details in CHANGELOG

from tst-reflect.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.