Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot find module '$lib/images/svelte-welcome.png?w=400&h=300&webp' or its corresponding type #532

Closed
SlavenDj opened this issue Apr 16, 2023 · 7 comments

Comments

@SlavenDj
Copy link

SlavenDj commented Apr 16, 2023

I am trying to set up vite imagetools for over a week and can not find the way to fix this error message in typescript. What should I do?

Vite imagetools: 4.0.18
TS: 4.9.3
Vite: 4.0.0
Sveltekit: 1.5.0
Svelte: 3.54.0

@Nickersoft
Copy link

Just ran into this same issue – @ts-ignore or @ts-expect-error helps, but obviously isn't ideal. Curious what kind of .d.ts file could be written to help alleviate these errors.

// @ts-expect-error
import walkthrough from './walkthrough.png?webp';

@SlavenDj
Copy link
Author

Better anything then nothing, thanks

@FlippingBinary
Copy link

There's no one-size-fits-all solution right now, but you can define modules based on the directives you use. For example, if you always use multiple directives and always explicitly use a format directive, you can declare modules like this:

declare module '*&webp' {
  const value: string
  export default value
}
declare module '*?webp' {
  const value: string
  export default value
}

Then, make sure you list the format directive explicitly at the end of your parameter list like this:

import example1 from './example.jpg?w=400&webp'
import example2 from './example.jpg?webp'

When you use it, TypeScript will know that it is a string because that's what you declared it as. The downside is you have to explicitly create unique modules based on the directives you use. The key is to pick some part of your directives list that you can always place last so TypeScript's module name pattern matching has something to latch onto. Then define the module based on the expected output for that set of directives. If you are generating multiple images from a single import, you might have to define a default array rather than a string, for example.

@FlippingBinary
Copy link

Alternatively, you can define a new directive that imagetools doesn't use because it seems to ignore unrecognized directives. You can use that directive to tell TypeScript what type of object to expect. See here: #160 (comment)

@benmccann
Copy link
Collaborator

There's some discussion here as well: #160 (comment)

@JonasKruckenberg
Copy link
Owner

As stated in #160 we're at the mercy of typescript here. I know it's incredibly annoying, but short of making a PR to typescript to increase the limit of allowed wildcards in a declare pattern there is nothing we can do

@JonasKruckenberg JonasKruckenberg closed this as not planned Won't fix, can't repro, duplicate, stale Apr 27, 2023
@FlippingBinary
Copy link

As stated in #160 we're at the mercy of typescript here. I know it's incredibly annoying, but short of making a PR to typescript to increase the limit of allowed wildcards in a declare pattern there is nothing we can do

@JonasKruckenberg May I suggest a possible approach? As of now, the library exports either a single item or an array of them based on specific directives that control the output type. To enhance the developer experience, the documentation could recommend that certain directives such as meta, picture, and others be specified last, and these directives could be used to name the wildcard module declarations. Additionally, it could be suggested to explicitly use the url directive to provide a hint to the compiler that a string or array of strings is being requested, even though that is the library's default behavior. While it's not strictly necessary for a basic implementation of this approach, the library could throw an error if that directive is used in conflict with other directives.

This approach would provide a low-barrier entry into offering built-in Typescript support and could give developers information about the properties of the exported types in the form of type hints. One downside is that the library user still needs to help the compiler figure out if they have a single item or an array of them, but this can be easily dealt with, and examples could be provided in the documentation.

For example, here's a rough implementation of this approach:

// imagetools.d.ts
declare module '*?url' {
  const value: string | string[];
  export default value;
}

declare module '*&url' {
  const value: string | string[];
  export default value;
}

declare module '*?meta' {
  const value: Metadata | Metadata[];
  export default value;
}

declare module '*&meta' {
  const value: Metadata | Metadata[];
  export default value;
}

declare module '*?metadata' {
  const value: Metadata | Metadata[];
  export default value;
}

declare module '*&metadata' {
  const value: Metadata | Metadata[];
  export default value;
}

declare module '*?picture' {
  const value: Picture | Picture[];
  export default value;
}

declare module '*&picture' {
  const value: Picture | Picture[];
  export default value;
}

declare module '*?srcset' {
  const value: Srcset | Srcset[];
  export default value;
}

declare module '*&srcset' {
  const value: Srcset | Srcset[];
  export default value;
}

If it is used in Typescript without a type assertion, the compiler would warn that it might not be an array (or might be some other type, depending on how it's actually implemented. The error would let the developer immediately know what types would be valid for that output type.

Obviously this example rather naively treats each type as being either an array or not an array, but I think it demonstrates the concept that there are only a handful of wildcard module declarations that are actually needed, along with some updates to the documentation, to solve this problem.

I believe this would be a significant enhancement to the library, and I hope you'll consider it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants