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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type Error: Generic type 'Block' requires 3 type arguments #497

Closed
1 task
hs-07 opened this issue Jan 3, 2024 · 5 comments 路 Fixed by #609
Closed
1 task

Type Error: Generic type 'Block' requires 3 type arguments #497

hs-07 opened this issue Jan 3, 2024 · 5 comments 路 Fixed by #609
Labels
bug Something isn't working prio:mid Medium priority

Comments

@hs-07
Copy link

hs-07 commented Jan 3, 2024

Describe the bug
Facing error of typescript regarding Block[ ]

image

Misc

  • Node version: latest
  • Package manager: npm
  • Browser: Google Chrome
  • I'm a sponsor and would appreciate if you could look into this sooner than later 馃挅
@hs-07 hs-07 added the bug Something isn't working label Jan 3, 2024
@frostcraftventuresltd
Copy link

I've just been doing something like below for now until there's an update.

const [blocks, setBlocks] = useState<Block<any, any, any>[]>([]);

    const insertHelloWorld = (editor: BlockNoteEditor) => {
        // Block that the text cursor is currently in.
        const currentBlock: Block<any, any, any> = editor.getTextCursorPosition().block;

        // New block we want to insert.
        const helloWorldBlock: PartialBlock<any, any, any> = {
            type: "paragraph",
            content: [{ type: "text", text: "Hello World", styles: { bold: true } }],
        };

        // Inserting the new block after the current one.
        editor.insertBlocks([helloWorldBlock as any], currentBlock, "after");
    };

The functionality still works fine just needed to get the error to no throw for me to publish it out to vercel.

Still wrapping my head around this project, hopefully can help contribute in the future as I'm going to heavily use this for other projects too.

@matthewlipski matthewlipski added prio:high High priority prio:mid Medium priority and removed prio:high High priority labels Jan 18, 2024
@zcf0508
Copy link

zcf0508 commented Jan 19, 2024

I find a way to resolve this problem, ccec336 (#524)

What's important is that

  1. editor need infer blockSpecs type correctly
  2. helloWorldBlock need declaration the type of block, like
const helloWorldBlock: PartialBlock<Pick<DefaultBlockSchema, 'paragraph'>, any, any> = {
    type: "paragraph",
    content: [{ type: "text", text: "Hello World", styles: { bold: true } }],
};

@YousefED
Copy link
Collaborator

For people facing this issue, most of this should be fixable removing the type annotation on the variable declaration. E.g. remove : Block[] in the original example.

When declaring Blocks, you can use as const to help the TS compiler. For example, see


Background: BlockNote is designed to be as type-safe as possible, whilst being extensible. So in BlockNote, you can define your custom schema / types for blocks / inlinecontent / styles, and this will be reflected in the Type System. This is done using generics.

Whilst this is really powerful (you get proper code completion and error checking), sometimes it can be a bit cumbersome. The above tips should help!

In the meantime, I'll also look into the suggestions by @zcf0508 and other ways to make this a bit more easier!

@aressss1
Copy link

aressss1 commented Jan 26, 2024

hi there, I'm facing a similar issue in PartialBlock.

here's the issue

Generic type 'PartialBlock' requires 3 type argument(s).ts(2314)
(alias) type PartialBlock<BSchema extends Record<string, BlockConfig>, I extends InlineContentSchema, S extends StyleSchema> = PartialBlocksWithoutChildren<BSchema, I, S>[keyof BSchema] & Partial<{
    children: PartialBlock<BSchema, I, S>[];
}>

here's my Editor.tsx in which I've used blocknote editor. This component receives initialContent : string from page.tsx(attached below).

"use client";

import {
  BlockNoteEditor,
  PartialBlock
} from "@blocknote/core";
import {
  BlockNoteView,
  useBlockNote
} from "@blocknote/react";
import "@blocknote/core/style.css";

import { useEdgeStore } from "@/lib/edgestore";

interface EditorProps {
  onChange: (value: string) => void;
  initialContent?: string;
  editable?: boolean;
};

const Editor = ({
  onChange,
  initialContent,
  editable
}: EditorProps) => {
  const { edgestore } = useEdgeStore();

  const handleUpload = async (file: File) => {
    const response = await edgestore.publicFiles.upload({ 
      file
    });

    return response.url;
  }

  const editor: BlockNoteEditor = useBlockNote({
      editable,
      initialContent: 
      initialContent 
      ? JSON.parse(initialContent) as PartialBlock[] 
      : undefined,
    onEditorContentChange: (editor) => {
      onChange(JSON.stringify(editor.topLevelBlocks, null, 2));
    },
    uploadFile: handleUpload
  })

  return (
    <div>
      <BlockNoteView
        editor={editor}
        theme={"dark"}
      />
    </div>
  )
}

export default Editor;

here's my page.tsx

'use client'

import Cover from "@/components/cover";
import Toolbar from "@/components/toolbar";
import { Skeleton } from "@/components/ui/skeleton";
import { api } from "@/convex/_generated/api";
import { Id } from "@/convex/_generated/dataModel";

import { useMutation, useQuery } from "convex/react";
import dynamic from "next/dynamic";
import { useMemo } from "react";

interface DocumentIdPageProps {
    params: {
        documentId: Id<"documents">
    }
}

const DocumentIdPage = ({
    params
}: DocumentIdPageProps) => {
    const Editor = useMemo(() => dynamic(() => import ("@/components/editor") , {ssr: false}) , [])

    const document = useQuery(api.documents.getById , {
        documentId: params.documentId
    })

    const update = useMutation(api.documents.update)

    const onChange = (content: string) => {
        update({
            id: params.documentId,
            content
        })
    }

    if (document === undefined) {
        return (
            <div>
                <Cover.Skeleton />
                <div className="md:max-w-3xl lg:max-w-4xl mx-auto mt-10" >
                    <div className="space-y-4 pl-8 pt-4" >
                        <Skeleton className="h-14 w-[50%]" />
                        <Skeleton className="h-4 w-[80%]" />
                        <Skeleton className="h-4 w-[40%]" />
                        <Skeleton className="h-4 w-[60%]" />
                    </div>
                </div>
            </div>
        )
    }
    
    if (document === null) {
        return (
            <div>
                Not Found
            </div>
        )
    }

    return ( 
        <div className="pb-40" >
            <Cover url={document.coverImage} />
            <div className="md:max-w-3xl lg:max-w-4xl mx-auto" >
                <Toolbar initialData={document} />
                <Editor
                    onChange={onChange} 
                    initialContent={document.content} 
                />
            </div>
        </div>
     );
}
 
export default DocumentIdPage;

I'll be grateful if someone helps me with this.

@YousefED
Copy link
Collaborator

YousefED commented Mar 5, 2024

Hi all! This should be greatly improved with the new version. Lmk if you still run into issues!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working prio:mid Medium priority
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants