如何从TypeScript泛型实例中提取目标类名以省略多余方法入参
可以去掉第一个参数
你完全可以直接从实例上提取类名,不需要额外传构造函数作为第一个参数,简化后的写法如下:
function save<T extends object>(entity: T) { // 不需要调用Object.getPrototypeOf,直接取实例的constructor属性即可 const apiPath = `/api/${entity.constructor.name.toLocaleLowerCase()}` return fetch(apiPath, { body: JSON.stringify(entity) }) } // 调用方式可以简化为 backendService.save(new User('Fractaliste'))
本地运行与Playground结果不一致的原因
出现差异通常是以下两个原因导致的:
- 编译目标版本不同
你本地的tsconfig.json中的target配置大概率是ES5或更低版本,TypeScript在低版本ES目标下转译类语法时,会改写构造函数的实现,导致constructor.name属性不符合预期。而TypeScript官方Playground默认使用高版本ES目标(ESNext),类语法会被保留原生实现,所以运行结果符合预期。你可以把本地的target调整为ES6及以上版本验证这个问题。 - 代码压缩混淆
如果你的项目启用了打包压缩(比如Webpack的Terser插件、Vite默认的生产构建配置),压缩工具会默认把类名替换为无意义的短字符来减小包体积,这时候constructor.name会变成类似t、n的随机短名,自然和预期的类名不一致。
更稳定的实现方案
依赖运行时类名拼接接口路径的方式,始终会受编译、压缩配置的影响,更稳妥的方案是给每个实体类添加静态的端点标识,避免运行时获取类名:
// 实体类定义 class User { static apiEndpoint = 'user' constructor(public name: string) {} } // save方法实现 function save<T extends object>(entity: T) { const clazz = entity.constructor as typeof Object & { apiEndpoint: string } return fetch(`/api/${clazz.apiEndpoint}`, { body: JSON.stringify(entity) }) }
这种实现完全不受编译配置和代码压缩的影响,稳定性更高。
内容的提问来源于stack exchange,提问作者Fractaliste
相关产品推荐
相关产品推荐

