Getting plugin-seo to work with TypeScript

default discord avatar
\ ឵឵឵last year
4

As an example:



import { default as _seo } from '@payloadcms/plugin-seo';
import { Page } from '../payload-types';

export const seo = _seo({
  collections: ['pages'],
  uploadsCollection: 'media',
  generateTitle: ({ doc }: { doc: Page; locale?: string }) => `My Site — ${doc.title}`,
  generateDescription: ({ doc }) => doc.excerpt,
});


With the typing for

generateTitle

's args,

${doc.title}

is happy, but

generateTitle

is not, because

Page

is more specific than the

T = any

type. Without the typing, as in the example

generateDescription

, it chokes on

doc

not having an

excerpt

property.



Mightn't it be possible for the library to type

T

as the union of the collection types specified? Or what are people doing here?



Bump!

  • discord user avatar
    jmikrut
    last year

    @jacobsfletch you may want to take a peek at this one

  • discord user avatar
    jacobsfletch
    last year

    It does look like those functions type the doc, check this out:

    https://github.com/payloadcms/plugin-seo/blob/main/src/types.ts#L9

    So you should type your whole function instead of just the args, then pass in the generic. Something like this:



    export const generateTitle: PluginConfig['generateTitle']<Page> = ({ doc }) => {
        // 'doc' should be typed as 'Page'
    }


    It looks like the plugin doesn't explicitly export function types which is why it's written this way. The readme says you can import

    GenerateTitle

    but I'm not sure this is true.

  • default discord avatar
    \ ឵឵឵last year

    Hmm, when I do that I get a syntax error on the opening angle brace for

    <Page>

    :


    const generateTitle: PluginConfig['generateTitle']<Page> = ({doc}) => `My Site — doc.title`

    ',' expected.ts(1005)


    Possibly this sheds some light:


    type GenerateTitle = PluginConfig['generateTitle'];
    const generateTitle: GenerateTitle<Page> = ({ doc }) => `My Site — ${doc.title}`;

    Type 'GenerateTitle' is not generic.ts(2315)


    Perhaps the author was trying to make it a template function, but ended up with a type variable instead?



    CFE


    type GenerateTitleX<T = any> = (args: { doc: T }) => string;
    const generateTitleXTyped: GenerateTitleX<Page> = ({ doc }) => `My Site — ${doc.title}`;
    const generateTitleXUntyped: GenerateTitleX = ({ doc }) => `My Site — ${doc.title}`;


    I'm reasonably sure that's what the author intended, given the type variable

    T

    in the current implementation is unused.



    I haven't really dug into that part of payload so much, maybe you know whether or not payload has something which can infer the type from a collection slug? Otherwise if people want typing it needs to be supplied explicitly as a parameter to the generic. With

    <T = any>

    , you won't get any errors—but there also won't be any inference.

    <T = unknown>

    if we want to force users to be explicit.

  • default discord avatar
    slavanossarlast year

    did this ever get resolved? also experiencing the same problem with typing the doc, and came to the same conclusion that the types have been written incorrectly. you should just be able to pass in a type with

    generateTitle<Page>

    and have the doc typed that way

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.