TypeScript不校验泛型类型?异步函数返回值类型不匹配无报错问题
TypeScript泛型类异步赋值未校验类型问题解析
问题重现
你在TypeScript中使用异步辅助函数返回特定泛型类型的数据库查询构建器时,发现TypeScript未校验泛型类型的正确性,允许将Foobar<string>赋值给Foobar<number>类型的变量,示例代码如下:
class Foobar<T> { } const asyncFunc = async (): Promise<Foobar<string>> => { return new Foobar(); } const caller = async (): Promise<void> => { const result: Foobar<number> = await asyncFunc(); // 此处未触发类型错误 }
原因分析
这是TypeScript的预期行为,核心原因在于TypeScript采用结构类型系统:类型兼容性由结构而非名称决定。
你的Foobar<T>类没有任何依赖泛型参数T的成员(属性、方法等),因此Foobar<string>和Foobar<number>的结构完全一致,TypeScript会认为这两个类型是兼容的,自然不会触发类型错误。
解决办法
要让TypeScript能区分不同泛型参数的Foobar实例,只需给类添加依赖泛型参数T的成员,让不同泛型参数的类结构产生差异:
方案1:添加泛型类型的属性
class Foobar<T> { // 添加一个类型为T的属性,可选或私有属性均可 private _typeMarker?: T; } const asyncFunc = async (): Promise<Foobar<string>> => { return new Foobar(); } const caller = async (): Promise<void> => { const result: Foobar<number> = await asyncFunc(); // 此时触发类型错误 }
方案2:添加依赖泛型的方法
class Foobar<T> { // 添加接收T类型参数的方法 setData(data: T): void {} // 或添加返回T类型的方法 getData(): T | undefined { return undefined; } } const asyncFunc = async (): Promise<Foobar<string>> => { return new Foobar(); } const caller = async (): Promise<void> => { const result: Foobar<number> = await asyncFunc(); // 触发类型错误 }
通过上述方式,TypeScript就能根据结构差异识别出不同泛型参数的Foobar实例不兼容,从而在赋值时触发类型校验错误,解决你在数据库代码中遇到的类型校验缺失问题。
内容的提问来源于stack exchange,提问作者hubbabubba
相关产品推荐
相关产品推荐

