Angular HttpClient如何让API返回值成为类实例以通过instanceof校验?
解决Angular HttpClient中
instanceof校验失效的问题 这个坑我踩过好多次!Angular的HttpClient在处理API返回的JSON时,只会把它转换成普通的JavaScript对象——哪怕你用了<Cow>这种TypeScript泛型标注,或者res as Cow的类型断言,都只是编译时的类型提示,并不会真的创建Cow类的实例。这就是为什么你的console.log(c instanceof Cow)会返回false的核心原因。
下面给你几个简便的解决方案,都能让instanceof正常工作:
方法1:给类添加静态转换方法
先改造你的Cow类,添加一个静态方法来把JSON对象转成类实例,同时用Object.assign简化构造逻辑:
export class Cow { name: string; age: number; // 构造函数接收部分属性,自动赋值 constructor(data: Partial<Cow>) { Object.assign(this, data); } // 静态方法:把JSON对象转为Cow实例 static fromJson(json: Partial<Cow>): Cow { return new Cow(json); } }
然后在你的请求里调用这个静态方法:
getCow() { return this.http.get<Cow>(ApiRoute.GET_COW, options) .map(res => Cow.fromJson(res)) // 这里把普通对象转成Cow实例 .toPromise() .then((c: Cow) => { console.log(c instanceof Cow); // 现在会返回true! }) }
方法2:直接在map中实例化类
如果不想写静态方法,也可以直接在map操作符里new出Cow实例,前提是你的Cow构造函数能处理传入的JSON对象:
// 先确保Cow的构造函数和方法1里的一样 getCow() { return this.http.get<Cow>(ApiRoute.GET_COW, options) .map(res => new Cow(res)) // 直接实例化 .toPromise() .then((c: Cow) => { console.log(c instanceof Cow); // true }) }
方法3:封装通用RxJS操作符(复用性更高)
如果你的项目里有很多类需要转换,可以封装一个通用的RxJS操作符,避免重复代码:
import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; // 通用转换操作符:把JSON对象转为指定类的实例 export function mapToInstance<T>(ctor: new (data: Partial<T>) => T) { return (source: Observable<Partial<T>>) => source.pipe(map(data => new ctor(data))); }
然后在请求中使用这个操作符(RxJS 6+需要用pipe包裹):
getCow() { return this.http.get<Cow>(ApiRoute.GET_COW, options) .pipe(mapToInstance(Cow)) .toPromise() .then((c: Cow) => { console.log(c instanceof Cow); // true }) }
最后再强调一下:TypeScript的类型标注和断言不会改变运行时的对象类型,只有通过类的构造函数创建实例,才能让instanceof识别出对象的类型哦。
内容的提问来源于stack exchange,提问作者Scott Clark
相关产品推荐
相关产品推荐

