Búsqueda de sitios web

¿Cómo se importa un componente de Svelte en un archivo de Typescript?


¿Es posible importar un componente de Svelte en un archivo de Typescript y que Rollup lo compile con éxito?

El siguiente código funciona como un archivo de Javascript, pero da errores cuando se convierte a Typescript, porque el compilador de TS no sabe cómo manejar un archivo .svelte:

import Component from './Component.svelte';

const foo = () => new Component({ target: document.body });

¿Existe una combinación de rollup-plugin-svelte y @rollup/plugin-typescript que preprocese el componente Svelte de tal manera que el compilador de TypeScript pueda incluir el código Svelte?


En caso de que un poco más de contexto sea útil, boardgame.io incluye un componente de depuración en el navegador construido con Svelte, que se incluye tanto en un cliente JS simple como en un componente cliente de React, y estamos tratando de actualizar nuestra configuración de Rollup precisamente para este escenario.

Respuesta #1

Solo para ampliar la respuesta de Rich, tenía curiosidad por investigar por qué importar Svelte ayudaba en algunas configuraciones.

el compilador de TS no sabe cómo manejar un archivo .svelte

Svelte resuelve esto (al menos en la versión en el momento de escribir, 3.35.0) distribuyendo un archivo en svelte/types/runtime/ambient.d.ts:

declare module '*.svelte' {
    export { SvelteComponentDev as default } from 'svelte/internal';
}

Esto efectivamente hace que el compilador de TS analice archivos .svelte. Por interés académico, también declara los tipos para toda la funcionalidad en tiempo de ejecución a la que un script en un archivo .svelte tiene acceso, como set_attributes() (ver svelte/internal para más información). Así que simplemente escribir declare module '*.svelte' {} solo te llevaría parcialmente, ya que también necesitarías esas declaraciones en tiempo de ejecución.

Entonces, para que el compilador de TypeScript pueda manejar archivos .svelte, necesitas - de una forma u otra - referenciar los tipos de ese archivo, svelte/types/runtime/ambient.d.ts. En realidad, este archivo se referencia indirectamente desde el archivo de tipos del punto de entrada del paquete (el valor especificado en el campo types del package.json de Svelte), types/runtime/index.d.ts, por lo que igualmente, podrías referenciar ese archivo de tipos del punto de entrada. Hacerlo sería la mejor práctica, ya que sería robusto frente a futuros refactors en la estructura del directorio.

Extender @tsconfig/svelte/tsconfig.json satisface esto porque el archivo tsconfig en cuestión hace referencia al módulo de nodo "svelte" a través de su propiedad compilerOptions.types:

{
  // ... Omitted...

  "compilerOptions": {
    // ... Omitted...

    "types": ["svelte"]
  }
}

Esto significa efectivamente que el contexto de compilación incluirá esta referencia:

/// <reference types="svelte" />

Podrías igualmente escribir esa misma línea tú mismo, aunque bien podrías extender el tsconfig de Svelte, ya que sería robusto frente a la evolución futura de Svelte.

La sugerencia de importar por efectos secundarios funciona por la misma razón:

import "svelte";

Descubrí que, aunque estaba extendiendo el tsconfig de Svelte, los tipos de Svelte no se estaban referenciando. Resultó que esto se debía a que terminé con esta línea en mi tsconfig:

{
  "extends": "@tsconfig/svelte/tsconfig.json",
  
  // ... Omitted...

  "compilerOptions": {
    // ... Omitted...

    "types": ["node"] // This overrides ["svelte"]!
  }
}

Lo arreglé reemplazando "types": ["node"] con "types": ["node", "svelte"].

Respuesta #2

Intenta agregar @tsconfig/svelte a tu proyecto, luego actualiza tu archivo tsconfig.json:

{
  "extends": "@tsconfig/svelte/tsconfig.json",
  "include": ["src/**/*"],
  "exclude": ["node_modules/*", "__sapper__/*", "public/*"],
}

Artículos relacionados