-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
Problem
There are many parts of the codebase where a function receives a Node and needs to determine whether its a Text, Element, or Editor, which roughly works as follows:
- Is it a Text?
- Does it have a
textproperty?- Then yes, its a Text. Done 😄
- Does it have a
- Is it an Element?
- Does it have a
childrenproperty?- Then yes, its a --oh wait it could still be an Editor, gotta make sure its not that first.
- Does it have a
- Is it an Editor?
- I'm going to assume this is a radioactive value and check every single property type and each of those properties' property types... (the current
isEditorcheck doesn't even properly check for every property of the current Editor object but I digress)- Okay, whew, that was a lot but yes this is definitely an editor 👍
- I'm going to assume this is a radioactive value and check every single property type and each of those properties' property types... (the current
The current hack to prevent a bloated isEditor subcall for every single isElement call is just to check for the apply function and assume anything with apply is an editor (and therefore not an Element).
slate/packages/slate/src/interfaces/element.ts
Lines 82 to 84 in 49f28e5
| // PERF: No need to use the full Editor.isEditor here | |
| const isEditor = typeof value.apply === 'function' | |
| if (isEditor) return false |
Solution
I have a few related suggestions:
Codify this check in the schema, that an Element is an object with a(Elements are always JSON, sochildrenproperty and without anapplyproperty.applybeing a function only for editors is already part of the spec, whoops!)- Implement a discriminator function(s) that can assume its input is a Node and only needs to choose between them. This saves on checking types of children, and editor can be checked by just checking the
applyproperty.
I'm thinking something like:as opposed to:function nodeIsText(node: Node): node is Text
function isText(node: any): node is Text
- Avoid using
isEditorwhenever possible, by either comparing the node to a known editor object or checking the length of its path. - (bonus) properly check for all properties of
EditorinisEditor
Alternatives
The specific property isn't crucial for my proposal, we could just as easily check for the (non)existence of (I really wrote that last part forgetting that it's already the case since Elements are JSON only...)onChange or operations or shouldMergeNodesRemovePrevNode. It also can be more specific, like specifically checking if its a function.
There are other ways this could be done, like turning Editor into a class or creating some new property/symbol for this check, but to me this way seemed the most in line with the current slate ethos.
Context
Happy to implement this myself, just wanted to hear other thoughts before running off on my own.