如何解决TypeScript联合类型中的“This expression is not callable”错误?
TypeScript无法关联数据库代理实例与对应列名类型的解决方案
问题场景
你实现了数据库表行的代理类ProxyDBRow,但在Svelte组件中使用联合类型的代理实例和列名时,TypeScript无法推断列名是否对应当前代理的表类型,导致调用getColumn时报错。代码示例如下:
type table1 = {id: number, col1: string, col2: string} type table2 = {id: number, colA: number, colB: number} type DBTable = table1 | table2 type DBColumnName<T extends DBTable> = keyof T type DBColumnValue<T extends DBTable, C extends DBColumnName<T>> = T[C] class ProxyDBRow<T extends DBTable> { data: T getColumn<C extends DBColumnName<T>>(name: C): DBColumnValue<T, C> { return this.data[name] } } // proxyComponent.svelte export let proxy: ProxyDBRow<table1> | ProxyDBRow<table2> export let attr: DBColumnName<table1> | DBColumnName<table2> const gc = () => { proxy.getColumn(attr) // 报错:expression not callable }
问题原因
当前代码中,proxy和attr都是独立的联合类型,TypeScript无法建立两者的关联关系——它无法确定传入的attr是否属于当前proxy对应的表的有效列名,因此判定调用不合法。而将proxy标注为ProxyDBRow<table1 | table2>时,keyof (table1 | table2)会取两个表的共有键(仅id),导致无法使用各表独有的列名,同样不符合需求。
解决方案
方案1:使用Svelte组件泛型(推荐)
通过给Svelte组件添加泛型约束,让proxy和attr的类型绑定在一起,TypeScript就能自动推断对应关系:
<script lang="ts" generics="T extends DBTable"> import type { DBTable, ProxyDBRow, DBColumnName } from './path-to-your-types'; export let proxy: ProxyDBRow<T>; export let attr: DBColumnName<T>; const gc = () => { proxy.getColumn(attr); // 类型检查正常通过 }; </script>
使用组件时,TypeScript会根据传入的proxy实例自动推断泛型T的具体类型,同时约束attr必须是该表的有效列名,从根源解决类型不匹配问题。
方案2:类型收窄+类型守卫
如果无法使用组件泛型,可以通过类型收窄明确proxy和attr的对应关系:
首先定义一个类型守卫函数,用于判断代理实例是否属于某张表:
function isProxyOfTable<T extends DBTable>( proxy: ProxyDBRow<DBTable>, column: keyof any ): proxy is ProxyDBRow<T> { return column in proxy.data; }
然后在调用getColumn前通过类型守卫收窄类型:
const gc = () => { if (isProxyOfTable<table1>(proxy, attr)) { proxy.getColumn(attr); // 此处proxy被推断为ProxyDBRow<table1>,attr为table1的列名 } else if (isProxyOfTable<table2>(proxy, attr)) { proxy.getColumn(attr); // 此处proxy被推断为ProxyDBRow<table2>,attr为table2的列名 } };
这种方式通过运行时检查配合类型断言,让TypeScript明确当前proxy和attr的类型匹配关系,消除报错。
内容的提问来源于stack exchange,提问作者Wyatt Strother
相关产品推荐
相关产品推荐

