-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Custom and Extended Types #3785
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See requested changes/comment inline. Thanks.
* The `CustomExtensions` interface extends types | ||
*/ | ||
|
||
export interface CustomExtensions { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think we need to update Slate's types for Text
and Element
to use ExtendedType
below? See @thesunny suggestion in the implementation issue - #3725. For instance:
// This would be Element as per Slate's definition
export type BaseElement = {
children: Text[]
}
// This would be Text as per Slate's definition
export type BaseText = {
text: string
}
export type Text = ExtendedType<"Text", BaseText>
export type Element = ExtendedType<"Element", BaseElement>
Then, the exported new types for Text
and Element
would be used in Slate's codebase and any developer's use of CustomExtensions
and ExtendedType
would propagate to the rest of the codebase.
Let's discuss if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue with this is that when you use ExtendedType
you are redefining Element or Text according to the definition you gave it inside your CustomExtension (once the user has defined it). If make the extended Element the new Element, a bunch of errors will be thrown during build, and pretty much 60% of the testcases will fail. Something that I found while making this PR was that in order to call Element's functions like isElement,
you need to use an alias. If you take a look at my isElement test case, you will see I am calling BaseElement.isElement. If I were to use Element.isElement, the program would not recognize the function because the type Extension is not able to fetch the functions as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I haven't had time to dive into the code so perhaps you could explain the issue and I might be able to help with a solution.
My question is, if the original object is defined as BaseText or BaseElement, and the extended type is created as Text and Element, are you saying that the methods don't come through to the extend type? It looks like in the typing we are doing:
export type ExtendedType<K extends string, B> =
unknown extends CustomExtensions[K]
? B
: B & CustomExtensions[K]
So shouldn't we get the proper types from both the original with the extensions added (ie. B & CustomExtensions[K]
)?
I may be misunderstanding the issue in which case a clarification would be helpful. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thesunny could use a review from your end. I think the code is looking more final now so it's probably a good time to review. Thanks!
@CameronAckermanSEL can you review too?
@@ -468,7 +472,7 @@ export const Node = { | |||
if (Text.isText(node)) { | |||
return node.text | |||
} else { | |||
let children = node.children as Array<Descendant> | |||
const children = node.children as Array<Descendant> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Array<x>
is more commonly written as x[]
const children = node.children as Array<Descendant> | |
const children = node.children as Descendant[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tim is totally correct but we should avoid the type assertion, if we can.
packages/slate/src/create-editor.ts
Outdated
@@ -217,7 +217,7 @@ export const createEditor = (): Editor => { | |||
(editor.isInline(node) || | |||
node.children.length === 0 || | |||
Text.isText(node.children[0]) || | |||
editor.isInline(node.children[0])) | |||
editor.isInline(node.children[0] as Element)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should be staying away from type assertions, if at all possible. There is a way to have the same code here w/o the type assertion.
Note: You will get some errors when you run yarn build because of the placeholder property in the Leaf interface in slate-react. Some help with that would be super appreciated! |
@@ -28,6 +27,8 @@ const Leaf = (props: { | |||
<String isLast={isLast} leaf={leaf} parent={parent} text={text} /> | |||
) | |||
|
|||
// const placeholder = 'placeholder' in leaf && leaf.placeholder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this @mdmjg? Let's remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ill remove
@@ -14,7 +14,7 @@ import { EDITOR_TO_ON_CHANGE } from '../utils/weak-maps' | |||
|
|||
export const Slate = (props: { | |||
editor: ReactEditor | |||
value: Node[] | |||
value: Element[] | |||
children: React.ReactNode | |||
onChange: (value: Node[]) => void | |||
[key: string]: unknown |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we might be able to get rid of this [key: string]: unknown
.
@@ -0,0 +1,18 @@ | |||
import { Descendant } from './node' | |||
|
|||
export interface BaseElement { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would move BaseElement
next to the Element
type and BaseText
next to the Text
type (i.e., back in the interface files for those types). Easier to read/follow the source that way.
@@ -65,7 +65,8 @@ export const GeneralTransforms = { | |||
if (Text.isText(node) && Text.isText(prev)) { | |||
prev.text += node.text | |||
} else if (!Text.isText(node) && !Text.isText(prev)) { | |||
prev.children.push(...node.children) | |||
const children = node.children as Element[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the type of editor.children
to Descendant[]
instead of Element[]
and am going to revert some of these changes. We can discuss but I think the more appropriate type for editor.children
is Descendant[]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay! I'll wait for you push then
Co-authored-by: Brent Farese <25846953+BrentFarese@users.noreply.github.com>
fd28053
to
a634d3d
Compare
889781c
to
7a95033
Compare
This seems an amazing PR!! I don't get why @CameronAckermanSEL, @ianstormtaylor and @thesunny should review this PR? They don't seem active. Waiting for their review will just make this PR never get merged and I don't think it is the best thing for the community. I would suggest that this PR got merged and if there are issues, they will be raised and addressed in a future release, it is not like if the project was currently in a stable state. Thank you @mdmjg for the awesome work you did in this PR and previous ones (#3762, #3784)! |
Co-authored-by: mdmjg <mdj308@nyu.edu>
7a95033
to
d20085f
Compare
@@ -9,6 +9,7 @@ import { | |||
Transforms, | |||
Path, | |||
} from 'slate' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this a potential circular dependency?
Thank you so much for all the effort put into this PR. This is going to be a great improvement for users who are in typescript. I had a few small questions about some code that looks like it was changed for reasons perhaps unrelated to this PR. Additionally, there was some code in the fixtures function that was changed that we might want to change back. The final concern I had was that there was a pretty massive amount of churn in Thanks again! |
Closing this in favor of #3835. |
Is this adding or improving a feature or fixing a bug?
feature
What's the new behavior?
Uses interfaces to support declaration merging and types for type discrimination.
In order to use declaration merging, the user must augment the Slate module. This detail could be explained in an additional example that could be added for this feature.
Have you checked that...?
yarn test
.yarn lint
. (Fix errors withyarn fix
.)yarn start
.)Does this fix any issues or need any specific reviewers?
Fixes: #3725 #3744
Reviewers: @thesunny @timbuckley @BrentFarese