carbon-design-system / carbon-components-svelte

Svelte implementation of the Carbon Design System
https://svelte.carbondesignsystem.com
Apache License 2.0
2.68k stars 261 forks source link

TypeScript cannot find CarbonTheme type when using Theme #1910

Closed iva2k closed 7 months ago

iva2k commented 7 months ago

When Theme is used with bind:theme in a .svelte file with TypeScript, pnpm check fails:

<script lang="ts">
  import {
    Theme,
+    type CarbonTheme,
  } from 'carbon-components-svelte';
-  let theme = 'g90';
+  let theme: CarbonTheme = 'g90';
</script>

<Theme bind:theme ... />

When theme is untyped, the error is "Type 'string' is not assignable to type 'CarbonTheme | undefined'."

Trying to add type CarbonTheme to the imports (to be able to add type to theme variable also fails).

iva2k commented 7 months ago

TypeScript is aware of CarbonTheme type used for theme property in Theme class, but it does not see it being exported anywhere.

adding this line:

export { CarbonTheme } from "./Theme/Theme.svelte";

to file "types/ index.d.ts" fixes the issue.

iva2k commented 7 months ago

Will you take a PR for that 1-liner?

metonym commented 7 months ago

I appreciate the attention to TypeScript DX, but may I suggest any of the following:

Use a const assertion

Casting the string as const narrows the type from a string to the value.

<script lang="ts">
  import { Theme } from "carbon-components-svelte";

  let theme = "g10" as const;
</script>

Use Svelte's built-in ComponentProps utility type to extract the prop from the component

<script lang="ts">
  import type { ComponentProps } from "svelte";
  import { Theme } from "carbon-components-svelte";

  let theme: ComponentProps<Theme>["theme"] = "g10";
</script>

Import the type directly

This one looks ugly and is the least future-proof.

<script lang="ts">
  import { Theme } from "carbon-components-svelte";
  import type { CarbonTheme } from "carbon-components-svelte/src/Theme/Theme.svelte";

  let theme: CarbonTheme = "g10";
</script>
iva2k commented 7 months ago

@metonym - Thanks! All 3 proposed workaround methods work.

ComponentProps method makes most sense.

Will be the missing type fixed in the package exports?

metonym commented 7 months ago

Will be the missing type fixed in the package exports?

@iva2k The types are currently auto-generated, and it's intentional that these local types (e.g., CarbonTheme) are not exported from the barrel index file. You can still import it directly, but I want to flag that the path can change in the future (hence why I think it's the least future-proof).

ComponentProps method makes most sense.

I also think the ComponentProps method is arguably the best as it does not need to care about exported interfaces at all, and it's officially supported by Svelte.