Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use Symbol.hasInstance for looser instanceof checks #989

Closed
wants to merge 1 commit into from

Conversation

jquense
Copy link

@jquense jquense commented Aug 10, 2017

fixes #491

I'm not entirely sure how to field test this but Symbol.for should be resilent over package boundaries since its all the same runtime.

*/

// eslint-disable-next-line flowtype/no-weak-types
export default function attachHasInstanceSymbol(ctor: Function): void {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what a better type here would be maybe GraphQLType?

@jquense
Copy link
Author

jquense commented Sep 2, 2017

any thoughts? I realize its a sort of silly change but it could potentially solve a bunch of annoying npm/yarn induced issues we see a lot on Gatsby

@felixfbecker
Copy link

Why does this have to be "attached"?
MDN has this example:

class MyArray {  
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}
console.log([] instanceof MyArray); // true

seems more natural to me to define it on the class

@KyleAMathews
Copy link

Just to add my vote to this — I hear someone complaining about Gatsby being broken due to the overly strict check every few days now.

},
});

ctor.prototype[Symbol.for(tag)] = true;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why Symbol.for() and not Symbol()?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one fetches a global symbol by name vs creating a new symbol:

Symbol('foo') == Symbol('foo') // false
Symbol.for('foo') == Symbol.for('foo') // true

Copy link

@felixfbecker felixfbecker Oct 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, but why is that desirable here? Imo the symbol should be private or if it's public, it should be exported, no retrievable for everyone through a magic string. You just need to save the symbol in a variable and reuse it. Otherwise you might as well just use a regular property.

Copy link
Author

@jquense jquense Oct 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its not using a symbol for privacy, it's to avoid muddying up people's namespace on the class for things they can use as property names. With the symbol you don't have to worry (nearly as much) about accidentally overwriting the tag in an instance when you just wanted to define an unrelated property. Incidentally this approach is how React tags elements as "ReactElements"

@bvaughn
Copy link

bvaughn commented Nov 1, 2017

This PR is important.

I hear someone complaining about Gatsby being broken due to the overly strict check every few days now.

This has impacted the reactjs.org repo twice now, most recently with reactjs/react.dev/pull/222. Each time it's cost me time and confusion to debug because the behavior is unexpected and confusing.

@leebyron
Copy link
Contributor

leebyron commented Dec 1, 2017

I'm going to close this PR since it doesn't solve the issue at hand, but instead moves it and creates new problems. See my comments in #996 for why this issue is more challenging than this PR's solution.

I would much prefer an approach which first improves the API by introducing predicate functions instead of relying on instanceof, and then leverages those predicate functions for producing much clearer and more actionable error messages.

I'd be more than happy to review PRs which tackled improving these errors

@leebyron leebyron closed this Dec 1, 2017
@jquense
Copy link
Author

jquense commented Dec 2, 2017

Hmm I don't think I understand the advantage to the predicate function of approach. isn't it essentially going to be the same logic except instead of instanceof checking a class tag, you have a function doing it? I'm not sure otherwise how'd you structure such functions other than doing a bunch of ugly tests for internal properties on the class instances, that hardly seems cleaner than leveraging language features designed for this case?

In any case I probably won't work on a follow-up PR, 4 months of no feedback makes it feel like it'd be a waste of time :/. Thanks again.

@jquense jquense deleted the use-has-instance branch December 20, 2017 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Redesign type/schema API to remove instanceof checks
6 participants