#Using TypeScript with custom client directives

12 messages · Page 1 of 1 (latest)

iron gazelle
#

I added a custom client directive to my Astro config, and it's working but the language server is throwing errors when it's included in Astro files.

<Splash client:tina site={site} />

Throws Property 'client:tina' does not exist on type 'IntrinsicAttributes & SplashProps'. I tried adding the following to a local declaration file but it didn't solve it:

declare module 'astro' {
  interface AstroClientDirectives {
    'client:tina'?: boolean
  }
}

tsconfig does point to where this declaration file + custom directive file live:

"typeRoots": ["./node_modules/@types", "./client-directives"],

Wondering if this is something else, since it's a React component / React interface that's throwing the error? How should I properly type this directive?

prisma archBOT
#
No-one around right now?

It looks like no-one has responded to your question yet. People might not be available right now or don’t know how to answer your question. Want an answer while you wait? Try asking our experimental bot in #1095492539085230272.

stray trout
#

Before doing anything else, have you tried Reload Window? If you use VS Code? Sometimes that does the trick with typescript detection.
I know that for vue you can register custom components like this:
https://docs.astro.build/en/guides/integrations-guide/vue/#options

Astro Documentation

Learn how to use the @astrojs/vue framework integration to extend component support in your Astro project.

stuck oasis
#

We have a way to add types for custom client directives, let me see if we have documentation

#

(otherwise, @boreal olive should know the answer)

#

Oh, the way you did it is how we recommend it, hmm, this should definitely be working

boreal olive
#

I think the declaration is right, maybe it's the typeRoots configuration 🤔 I think we can remove that configuration, and instead use "include" to make sure it covers the ./client-directive.d.ts file (might be better to be explicit about the extension)

iron gazelle
#

hmm I couldn't get it working just now with "include" (and renaming the declaration file). fyi I think the main thing I'm doing that's not part of the docs is writing the integration directly in my astro.config file, not importing it and not packaging it as a library/dependency (yet). Could that be the problem?

So I have client-directives/tina.mjs which is:

/**
 * @type {import('astro').ClientDirective}
 */
export default (load) => {
  try {
    const isEditor =
      window.frameElement && window.frameElement.id === 'tina-iframe'
    if (isEditor) {
      load().then((hydrate) => hydrate())
    }
  } catch (e) {
    console.error(e)
  }
}

And this integration defined in astro.config.mjs (maybe needs to be .ts?)

/**
 * @returns {import('astro').AstroIntegration}
 */
const tina = () => ({
  name: 'tina-cms',
  hooks: {
    'astro:config:setup': ({ addClientDirective }) => {
      addClientDirective({
        name: 'tina',
        entrypoint: './client-directives/tina.mjs',
      })
    },
  },
})

Have tried putting that declaration file in client-directives as index.d.ts, client-directives.d.ts, and astro/index.d.ts. I can try packaging as a dependency too, just been hoping to sort out these little things first.

boreal olive
# iron gazelle hmm I couldn't get it working just now with `"include"` (and renaming the declar...

Sorry I miss following up on this! The way you setup is similar to how we test it so it should work too https://github.com/withastro/astro/tree/6fafb3d15d75209bce5f2d1f3a627f3e05123fb9/packages/astro/e2e/fixtures/custom-client-directives. E.g. We have the directives in the client-password.js file, and the dts in src/client-directive-types.d.ts.

I remember replicating the setup in a normal project and it works too, but maybe it has changed.

iron gazelle
iron gazelle
#

ok nevermind! astro check is happy now too. I might have had to run build/dev for it to catch up, not sure. anyway seems like export {} solved it, thanks!

boreal olive
#

Awesome! Yeah the export {} could be the issue since TypeScript has subtle differences between a "script" and "module" .ts file. export {} makes it a "module".

If you want to stick with a "script", you can remove the export {} and wrap the declare module 'astro' block with declare global { ... } block and it should also work (i think)