Svelte 5.56.0 把 type 三元表达式误判为声明
Svelte 5.56.0 中以 type 变量开头的合法表达式,可能被误判为不允许的模板声明。区分语法误识别,局部改名或采用 5.56.1 修复。
模板里只写了一个三元表达式,编译却报声明标签只能使用 let 或 const。如果表达式以变量 type 开头,且问题紧接着升级到 Svelte 5.56.0 出现,可以检查解析器是否把这个普通变量误当成 TypeScript 的 type 声明。
具体触发可以放在选项文本中:
<script lang="ts">
const assetTypes = ['a', 'b', 'all'] as const;
let filterType = $state('all');
</script>
<select bind:value={filterType}>
{#each assetTypes as type (type)}
<option value={type}>{type === 'all' ? 'All types' : type}</option>
{/each}
</select>
这里 type 是 each 块声明的变量,不是类型别名。Svelte 5.55.0 没有这条具体回归,5.56.1 已修复对应解析。不要把它概括成 Svelte 不支持三元运算符。
为什么提示会指向不存在的声明
type 在 TypeScript 中是上下文关键字,也可以合法用作变量名。5.56.0 的模板声明识别使用字符规则预判,遇到 type === ... 等形态时,可能在真正解析表达式前就将它归入不支持的声明。
因此,错误信息中的 declaration_tag_invalid_type 不等于组件里一定写了 {type Foo = ...}。先检查报错位置完整表达式,再核对编译器版本。模板若真的包含不允许的类型声明,仍要按模板语法调整,不能期待升级替它放开限制。
5.56.1 改为先解析 type 开头的内容,再区分表达式与声明。type instanceof Foo、比较和算术等表达式也属于这一判断边界,修复并非只针对问号前后补空格。
保持原判断,局部改掉变量名也能避开
暂时不能更新时,可以把模板中的 each 局部变量改成含义明确的名字,并同步修改这个块内的引用:
{#each assetTypes as assetType (assetType)}
<option value={assetType}>
{assetType === 'all' ? 'All types' : assetType}
</option>
{/each}
示例沿用前面的 assetTypes 与 filterType。改名不需要改变选项值,也不需要修改传给服务端的数据字段。若真实组件还有插槽、事件或嵌套块使用这个局部变量,应一起核对作用域,不能全仓库替换字符串 type。
另一条处理路径是在项目兼容范围内采用包含修复的编译器,保留原模板。框架项目需核对真正负责构建的 Svelte 版本;只有运行时包清单变化,而编译过程仍使用旧依赖,不能修正解析阶段。
完成后,检查原表达式能够编译,选中 all 时显示替换文本,其他项仍显示自己的值,选择绑定也没有改变。出现另一条模板错误时保留完整信息继续判断,不要把所有声明标签报错都归到 type 变量名上。


