Comments (12)
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.
But okay, there will be base variant getType(val: any): Type
and config option reflection.usePrototype: boolean = false
.
That's fair. ๐
from tst-reflect.
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:
- "Inheritance and the prototype chain" (MDN) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Bad_practice_Extension_of_native_prototypes
Warning: One misfeature that is often used is to extend Object.prototype or one of the other built-in prototypes.
This technique is called monkey patching and breaks encapsulation. While used by popular frameworks such as Prototype.js, there is still no good reason for cluttering built-in types with additional non-standard functionality.
The only good reason for extending a built-in prototype is to backport the features of newer JavaScript engines, like Array.forEach.
- "Why you should not modify a JavaScript object prototype" https://flaviocopes.com/javascript-why-not-modify-object-prototype/
- "Maintainable JavaScript: Donโt modify objects you donโt own" https://humanwhocodes.com/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
from tst-reflect.
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.
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.
@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.
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.
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.
@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.
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.
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.
Available from:
[email protected]
[email protected]
Version details in CHANGELOG
from tst-reflect.
Related Issues (20)
- Support decorators from TS 4.8 HOT 2
- Unable to access parameter decorators HOT 2
- [BUG] Set not comparable HOT 1
- [Question] Anyway to add it as angular transformer HOT 18
- [BUG] tst-reflect: You call getType() method directly. You have probably wrong configuration, because tst-reflect-transformer package should replace this call by the Type instance. HOT 8
- [BUG] type metadata HOT 6
- Can't get `getType<T>()` to work HOT 5
- Participation in the new version of the system HOT 52
- [BUG] Watch mode HOT 1
- Can't get function to work with create-react-app HOT 3
- [BUG] Uncaught ReferenceError: _รr is not defined HOT 4
- [Question] npm package using tst-reflect cannot be imported HOT 1
- [BUG] Union properties are broken HOT 5
- [BUG] TS 4.9 - "[ERR] tst-reflect: You call getType() method directly..." error when following base usage examples. HOT 17
- [Question] Comparison of Array types HOT 9
- [Question] How to get field type inside a decorator HOT 2
- [Question] Vite support HOT 3
- [Question] Does this work with functions? HOT 2
- Is there a way to use it with nestjs [Question] HOT 1
- Generic Type at runTime HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tst-reflect.