prismicio / prismic-react

React components and hooks to fetch and present Prismic content
https://prismic.io/docs/technologies/homepage-reactjs
Apache License 2.0
154 stars 40 forks source link

Typescript types...? #42

Closed martaver closed 3 years ago

martaver commented 4 years ago

Hi guys, I notice that prismic-javascript has typings available. Any plans to release typings for this?

fandy commented 4 years ago

Would be super useful especially when creating serializers.

rubas commented 4 years ago

Same goes for prismicio/prismic-richtext. Any chance of an update with types? Would be highly appreciated.

rubas commented 4 years ago

As a starting point ...

import { Elements } from "prismic-richtext"
import { htmlSerializerType } from "prismic-reactjs"
const htmlSerializer: htmlSerializerType = (type, _element, _content, children, key) => {
  switch (type) {
    case Elements.heading1:
      return <Heading1 key={key}>{children}</Heading1>
    case Elements.heading2:
      return <Heading2 key={key}>{children}</Heading2>
    case Elements.heading3:
      return <Heading3 key={key}>{children}</Heading3>
    case Elements.heading4:
      return <Heading4 key={key}>{children}</Heading4>
    case Elements.heading5:
      throw new Error("Not implemented")
    case Elements.heading6:
      throw new Error("Not implemented")
    case Elements.paragraph:
      return <Paragraph key={key}>{children}</Paragraph>
    /*
    case Elements.preformatted: return serializePreFormatted(element);
    case Elements.strong: return serializeStandardTag('strong', element, children);
    case Elements.em: return serializeStandardTag('em', element, children);
    case Elements.listItem: return serializeStandardTag('li', element, children);
    case Elements.oListItem: return serializeStandardTag('li', element, children);
    case Elements.list: return serializeStandardTag('ul', element, children);
    case Elements.oList: return serializeStandardTag('ol', element, children);
    case Elements.image: return serializeImage(linkResolver, element);
    case Elements.embed: return serializeEmbed(element);
    case Elements.hyperlink: return serializeHyperlink(linkResolver, element, children);
    case Elements.label: return serializeLabel(element, children);
    case Elements.span: return serializeSpan(content);
    */
    default:
      return null
  }
}

prismic.d.ts

declare module "prismic-richtext" {
  const Elements: {
    heading1: string
    heading2: string
    heading3: string
    heading4: string
    heading5: string
    heading6: string
    paragraph: string
    preformatted: string
    strong: string
    em: string
    "list-item": string
    "o-list-item": string
    "group-list-item": string
    "group-o-list-item": string
    image: string
    embed: string
    hyperlink: string
    label: string
    span: string
  }
}

declare module "prismic-reactjs" {
  type RichText = {
    html?: string | null
    text?: string | null
    raw?: RichTextBlock | null
  }

  type RichTextSpan = {
    start: number
    end: number
    type: string
    text: string
  }

  type RichTextBlock = {
    type: string
    text: string
    spans: RichTextSpan[]
  }

  type htmlSerializerType = (
    type: string,
    element: RichTextSpan,
    content: string | null,
    children: React.ReactNode,
    key: number
  ) => React.ReactElement | null

  const RichText: React.FC<{ render: RichTextBlock; htmlSerializer: htmlSerializerType }>
}
Gholgot commented 4 years ago

Hi, I made a PR to fix this issue. Feel free to comment It or share advices to improve what has been made 😃

ohlr commented 4 years ago

I tried to install @types/prismic-reactjs but there is no such package. How do I make use of your PR @Gholgot ? It should be merged in the current release 1.3.0

ohlr commented 4 years ago

I am still struggling on the PR of @Gholgot Do I have to use typings for this to work? I tried "typeRoots": ["node_modules/prismic-reactjs/typings/"], in my tsconfig with no success.

Is there any chance to add this to DefinitelyTyped?

schwigri commented 4 years ago

I have prismic-reactjs installed from NPM, version 1.3.1. I looked in node_modules/prismic-reactjs folder and there is indeed the typings/index.d.ts file. However, my VS Code behaves as if there is not a declaration, and when I open that file, it has many errors:

Line Error
33 Value of type 'typeof Component' is not callable. Did you mean to include 'new'? ts(2348)
35 Initializers are not allowed in ambient contexts. ts(1039)
41 Type parameter name cannot be 'any'. ts(2368)
41 Generic type 'DOMElement<P, T>' requires 2 type argument(s). ts(2314)
48, 49, 50, 51 Type parameter name cannot be 'any'. ts(2368)
58 'RichText' refers to a value, but is being used as a type here. ts(2749)
61 'string' is declared but its value is never read. ts(6133)
61 Initializers are not allowed in ambient contexts. ts(1039)
61 Type '<string>() => Date' is missing the following properties from type 'Date': toDateString, toTimeString, toLocaleDateString, toLocaleTimeString, and 38 more. ts(2740)
61 Type parameter name cannot be 'string'. ts(2368)
68 'string' is declared but its value is never read. ts(6133)
68 A type literal property cannot have an initializer. ts(1247)
68 Type '<string>() => Date' is missing the following properties from type 'Date': toDateString, toTimeString, toLocaleDateString, toLocaleTimeString, and 38 more. ts(2740)
68 Type parameter name cannot be 'string'. ts(2368)

I am not familiar enough with TypeScript or Prismic to be able to really understand/implement a fix, or even understand if this may be an issue with my own configuration.

ohlr commented 4 years ago

@schwigri I can confirm your issue with VScode (if you resolve it please let me know.)

ohlr commented 4 years ago

https://github.com/prismicio/prismic-reactjs/issues/52 I believe this is the issue why it's not working

noblica commented 4 years ago

52 I believe this is the issue why it's not working

Moving index.d.ts out of the typings folder, and into the root folder seems to make the error go away. But I think the returned types are still incorrect. For example - RichText is returned as an any type, when it should be a React Component.

Also, the prismic-reactjs typings use react typings, but they aren't imported anywhere. Not sure if that might be an issue as well :/

martaver commented 4 years ago

@noblica it's true... the types in the typings folder are fubar. I copied them manually into my own project as a temporary measure and even then, after hacking at them to make them fit, they were thoroughly broken.

Not fun.

Step it up, prismic. This is just lazy.

sessa commented 4 years ago

@noblica it's true... the types in the typings folder are fubar. I copied them manually into my own project as a temporary measure and even then, after hacking at them to make them fit, they were thoroughly broken.

Not fun.

Step it up, prismic. This is just lazy.

I made a pr #61 -- I am copying these into my project. Curious if you do the same if you will see any success.

If these look good, the project would need to be updated to build the types for distribution.

noblica commented 4 years ago

@sessa These look pretty good, thanks! I'll try them out.

noblica commented 4 years ago

Maybe this should go under the main prismic-js repo, but what do you think about adding types for the fields? For example, if your query returns a title, you get this structure:

Screenshot from 2020-05-15 13-11-05

So couldn't we have a PrismicTitle type (or something like that) with the following structure?

{
  "type": "heading1" | "heading2" | "heading3" | ....,
  "text": string,
  "spans": Span[]
}

What do you think?

schwigri commented 4 years ago

@noblica, do you know if there is a document outlining all of the possible Rich Text array items? I wrote a very generic RichTextBlock type to #61 in a comment, but I believe it could be expanded upon.

noblica commented 3 years ago

Hey @schwigri I think not. I think we just have to go through the existing code. A good starting point seems to be the src/richtext.js file:

switch(type) {
    case Elements.heading1: return serializeStandardTag('h1', element, children, index);
    case Elements.heading2: return serializeStandardTag('h2', element, children, index);
    case Elements.heading3: return serializeStandardTag('h3', element, children, index);
    case Elements.heading4: return serializeStandardTag('h4', element, children, index);
    case Elements.heading5: return serializeStandardTag('h5', element, children, index);
    case Elements.heading6: return serializeStandardTag('h6', element, children, index);
    case Elements.paragraph: return serializeStandardTag('p', element, children, index);
    case Elements.preformatted: return serializeStandardTag('pre', element, children, index);
    case Elements.strong: return serializeStandardTag('strong', element, children, index);
    case Elements.em: return serializeStandardTag('em', element, children, index);
    case Elements.listItem: return serializeStandardTag('li', element, children, index);
    case Elements.oListItem: return serializeStandardTag('li', element, children, index);
    case Elements.list: return serializeStandardTag('ul', element, children, index);
    case Elements.oList: return serializeStandardTag('ol', element, children, index);
    case Elements.image: return serializeImage(linkResolver, element, index);
    case Elements.embed: return serializeEmbed(element, index);
    case Elements.hyperlink: return serializeHyperlink(linkResolver, element, children, index);
    case Elements.label: return serializeLabel(element, children, index);
    case Elements.span: return serializeSpan(content);
    default: return null;
  }
jordiup commented 3 years ago

Yay! an open issue that's been closed :)

I just had to run: yarn upgrade prismic-reactjs !