Skip to content

zvelte-check reports false positive errors #1

@devdinu

Description

@devdinu

zvelte-check version: 0.2.0
Date: 2026-04-22

We've been evaluating zvelte-check as a drop-in replacement for svelte-check in a large pnpm workspace monorepo with multiple Svelte packages (mix of Svelte 4 and Svelte 5 patterns). svelte-check reports 0 errors across all packages, but zvelte-check reports hundreds of false positives. All fall into 3 categories.


1. CSS/HTML text parsed as TypeScript identifiers

The transformer extracts identifiers from raw AST node source slices before validating them as actual JavaScript expressions. CSS property values, CSS units, and plain HTML text content end up emitted as void name; statements, which tsgo rejects as undefined identifiers.

Examples

Cannot find name 'calc'.
Cannot find name 'rem'.
Cannot find name 'vw'.
Cannot find name 'flex'.
Cannot find name 'container'.
Cannot find name 'hidden'.
Cannot find name 'head'.
Cannot find name 'style'.
Cannot find name 'DevOps'.
Cannot find name 'engineers'.

These come from pages with rich HTML/CSS content — marketing pages, documentation, microsites — where <style> blocks, inline style= attributes, and plain text are present alongside Svelte template expressions.

Expected behavior

CSS values like flex, rem, calc and plain text like Sourcegraph should never be extracted as TypeScript identifiers. Only actual Svelte {expressions} should be.


2. Bad TypeScript syntax from $props() destructuring

The generated .svelte.ts output contains invalid TypeScript for certain $props() patterns, producing syntax errors.

Error patterns

';' expected.
',' expected.
'=' expected.
')' expected.
'=>' expected.
Expression expected.
Property or signature expected.

Failing input patterns

const destructuring (Svelte 5)

<script lang="ts">
    interface Props { notes: string[] }
    const { notes }: Props = $props()
</script>

zvelte-check appears to only recognize let as the declaration keyword before $props(). When const is used, the transform produces invalid TS output.

Complex $$Props types (Svelte 4)

<script lang="ts">
    import type { ComponentProps } from 'svelte'
    import FileIcon from './FileIcon.svelte'

    type $$Props = { language: string } & Omit<ComponentProps<FileIcon>, 'file'>
    export let language: string
</script>
<script lang="ts">
    import type { SVGAttributes } from 'svelte/elements'

    type $$Props = SVGAttributes<SVGElement> & { svgPath: string; inline?: boolean }
    export let svgPath: string
    export let inline: boolean = false
</script>
<script lang="ts">
    import type { HTMLButtonAttributes } from 'svelte/elements'

    type $$Props = { on: boolean } & HTMLButtonAttributes
    export let on: boolean
</script>

Complex intersection types, generic types (Omit<...>), and mapped types in $$Props declarations appear to cause the transformer to emit malformed TypeScript.

Expected behavior

Both const and let destructuring with $props() should produce valid TypeScript. Svelte 4 $$Props patterns with complex type expressions should also transform correctly.


3. Missing named exports from *.svelte wildcard module

When one package imports named exports from .svelte files in another package, the wildcard *.svelte ambient module declaration reports that the named export doesn't exist.

Example

Given a component library package that re-exports types from .svelte files:

// @my-org/uikit/src/lib/index.ts
export type { AlertVariant, AlertStyleOverrides } from './components/alert/Alert.svelte'
export type { ButtonSize, ButtonVariant } from './components/button/Button.svelte'
export type { IconComponent, Props } from './components/icon/Icon.svelte'

And a consuming package in the same monorepo:

import { Icon, type IconComponent } from '@my-org/uikit'

zvelte-check reports:

Module '"*.svelte"' has no exported member 'AlertVariant'.
Module '"*.svelte"' has no exported member 'ButtonVariant'.
Module '"*.svelte"' has no exported member 'IconComponent'.
Module '"*.svelte"' has no exported member 'Props'.
Module '"*.svelte"' has no exported member 'ThemeMode'.

Root cause

Only .svelte files in the current workspace are transformed to .svelte.ts with real exports. Files from referenced packages are not transformed, so tsgo falls back to the wildcard *.svelte ambient module stub which only has a default export.

Expected behavior

Named exports from .svelte files in referenced/imported packages should resolve correctly, either by transforming those files too or by generating per-module declarations for known imports.


Environment

  • macOS (darwin arm64)
  • zvelte-check 0.2.0
  • pnpm workspace monorepo
  • Mix of Svelte 4 (export let, type $$Props) and Svelte 5 ($props(), interface Props) patterns
  • svelte-check reports 0 errors on the same codebase

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions