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

core(tsc): make CPUNode and NetworkNode a discriminated union #5548

Merged
merged 5 commits into from
Jun 26, 2018

Conversation

brendankenny
Copy link
Member

@brendankenny brendankenny commented Jun 22, 2018

@patrickhulce this is what I mentioned a while back (in #5072). The Node type passed around becomes a union of CPUNode | NetworkNode, which means things inside e.g. an if (node.type !== 'network') block that node becomes a CPUNode with no cast or anything.

The downsides are
a) naming (but we can tweak) and
b) double casts of this within the Node class since the compiler doesn't know that this isn't an incompatible subclass of Node (so first cast to Node, then cast to CPUNode | NetworkNode.

@brendankenny
Copy link
Member Author

b) double casts of this within the Node class

other options:

  • @ts-ignore, downside is that if Node or NodeType become incompatible it wouldn't be caught in these spots
  • type guard support just landed for jsdoc, so we could have a function that encapsulates the double cast if (isNodeType(this)) { /* do something NodeTypey with this */ }, but that involves functional changes that actually execute at runtime whereas this PR only touches non-functional type annotations...

@brendankenny
Copy link
Member Author

er, and last option, we don't do this and keep casting. Not a big deal if not :)

@wardpeet
Copy link
Collaborator

wardpeet commented Jun 25, 2018

type guard support just landed for jsdoc, so we could have a function that encapsulates the double cast if (isNodeType(this)) { /* do something NodeTypey with this */ }, but that involves functional changes that actually execute at runtime whereas this PR only touches non-functional type annotations...

I'm probably not getting it 100% but you will always need some kind of if statement right?

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

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

I think this is great! one main Q that I think would make it 💯

const CPUNode = require('../../../lib/dependency-graph/cpu-node'); // eslint-disable-line no-unused-vars
const NetworkNode = require('../../../lib/dependency-graph/network-node'); // eslint-disable-line no-unused-vars

/** @typedef {Node.NodeType} NodeType */
Copy link
Collaborator

Choose a reason for hiding this comment

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

is this a necessary thing, or just prefer it over Node.NodeType everywhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess I prefer it over Node.NodeType, but honestly it had become rote c/p by this file so I didn't really think of that possibility when both are needed in a file :)

@@ -5,6 +5,12 @@
*/
'use strict';

/**
* A union of all types derived from Node, allowing type check disrimination
Copy link
Collaborator

Choose a reason for hiding this comment

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

discrimination :)

Copy link
Member Author

Choose a reason for hiding this comment

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

done

/**
* A union of all types derived from Node, allowing type check disrimination
* based on `node.type`. If a new node type is created, it should be added here.
* @typedef {import('./cpu-node.js') | import('./network-node.js')} NodeType
Copy link
Collaborator

Choose a reason for hiding this comment

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

how would you feel about calling this one Node and the real base class BaseNode or something? it feels weird to say that all those methods accept a thing of type NodeType instead of saying they expect a Node

Copy link
Member Author

Choose a reason for hiding this comment

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

it feels weird to say that all those methods accept a thing of type NodeType instead of saying they expect a Node

it does feel weird but I couldn't think of a decent alternative name for Node :) This suggestion sounds good, will do

@brendankenny
Copy link
Member Author

whereas this PR only touches non-functional type annotations...

I'm probably not getting it 100% but you will always need some kind of if statement right?

yes, true, I meant non-functional as in no more functionality than what you'd already be doing to tell if something was a CPUNode or a NetworkNode :)

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

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

LGTM!

@brendankenny brendankenny merged commit 9c5b76c into master Jun 26, 2018
@brendankenny brendankenny deleted the nodeunion branch June 26, 2018 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants