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!
@jacobsfletch you may want to take a peek at this one
It does look like those functions type the doc, check this out:
https://github.com/payloadcms/plugin-seo/blob/main/src/types.ts#L9So 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.
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.
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
Discord
online
Get help straight from the Payload team with an Enterprise License.