facebook / docusaurus

Easy to maintain open source documentation websites.
https://docusaurus.io
MIT License
56.58k stars 8.49k forks source link

TypeScript emits type errors “Cannot find modules '<path of raster images>' when raster images are imported #8683

Open tats-u opened 1 year ago

tats-u commented 1 year ago

Have you read the Contributing Guidelines on issues?

Prerequisites

Description

In current Docusaurus version (2.x), no declare module "*.png", declare module "*.jpg", and so on are not defined and we get type erros when we try to import raster images unlike Next.js. We have to avoid this kind of errors by adding these ambient declarations to src/index.d.ts.

To make matters worse, the plugin-ideal-image changes the type of imported supported images from string to {src: {src: string, width: ...}, preSrc: string}. (related: #8684) We will have to select proper ambient declarations. Next.js, which has a similar feature, resolves this problem by next-env.d.ts like:

/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

Reproducible demo

https://codesandbox.io/s/docusaurus-bug-report1-kptbhq

Steps to reproduce

  1. Setup using TypeScript template
  2. Add import picture from "../../blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg"; and <img src={picture} alt="" /> to src/pages/index.tsx

Expected behavior

No type errors

Actual behavior

Cannot find module '../../blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg' or its corresponding type declarations.ts(2307)

image

Your environment

Self-service

Josh-Cena commented 1 year ago

Indeed, it seems we never expect someone to actually use import statements with .png files 😅 Our docs do recommend src={require("...").default} because it's several lines shorter.

Unfortunately ambient declarations cannot override each other's default export. Do you know how this should work? Should we have declare module "*.png" under a separate named export and let users choose between the declarations from module-name-aliases or plugin-ideal-image?

tats-u commented 1 year ago

I think we can refer to Next.js.

https://nextjs.org/docs/basic-features/typescript#existing-projects

As for applying this to Docusaurus, I don't think .d.ts should be ignored. However i think it should be generated or modified if needed when yarn start.

slorber commented 1 year ago

Note: the ideal plugin image returns string | object because in dev it can be disabled while it's always enabled in prod.

Due to the modular nature of Docusaurus, if we were to generate something similar to next-env.d.ts that would probably require a new plugin lifecycle so that the generated types are different if the image plugin is enabled/disabled.

I'd prefer to not rush into implementing this. Maybe let's see if we can find other plugins that would benefit from this. Adding local typedefs yourself is a good temporary workaround.