TypeScript中如何正确将基类型转为扩展类型?URL扩展实例答疑
URL扩展对象打印异常的原因与解决方法
现象原因
你遇到的问题核心在于URL是JavaScript的内置特殊对象,它的href、origin等属性并不是实例的自有属性,而是定义在URL.prototype上的访问器属性(getter)。
当你用扩展运算符...url创建新对象时,只会复制实例的可枚举自有属性,而URL实例的自有属性其实是[Symbol(context)]和[Symbol(query)]这些内部符号属性——那些你期望的URL属性因为是原型链上的访问器,所以不会被复制到新对象里。
TypeScript的URLEx = URL & { custom: string }只是类型层面的交集声明,它不会改变运行时对象的实际结构,所以类型检查通过了,但运行时的新对象并没有继承URL的原型,自然无法展示那些访问器属性。
解决方法
要不用手动映射所有属性实现需求,关键是让新对象继承URL的原型链,这样就能正常访问那些访问器属性。下面是两种可行方案:
方案1:直接给原URL实例添加属性(会修改原对象)
如果不需要保留原URL对象的纯净性,可以直接给它添加custom属性:
type URLEx = URL & { custom: string; }; const url = new URL("http://localhost:3000/foo/var"); // 用类型断言告诉TS这个URL实例现在符合URLEx类型 (url as URLEx).custom = "hello"; console.log(url); // 输出: // { // href: 'http://localhost:3000/foo/var', // origin: 'http://localhost:3000', // protocol: 'http:', // username: '', // password: '', // host: 'localhost:3000', // hostname: 'localhost', // port: '3000', // pathname: '/foo/var', // search: '', // searchParams: URLSearchParams {}, // hash: '', // custom: 'hello' // }
方案2:创建新的URL实例并添加属性(不修改原对象)
如果需要保留原对象,就基于原URL的地址创建新实例,再添加custom属性:
type URLEx = URL & { custom: string; }; const url = new URL("http://localhost:3000/foo/var"); // 创建新的URL实例,继承URL原型链 const url_x = new URL(url.href) as URLEx; url_x.custom = "hello"; console.log(url_x); // 输出符合预期的所有URL属性加custom字段
这种方法的核心是新实例继承了URL.prototype,所以那些访问器属性能正常被读取和打印,同时拥有自己的custom自有属性。
内容的提问来源于stack exchange,提问作者Yanick Rochon
相关产品推荐
相关产品推荐

