我正在使用公共RESTful API,它返回包含指向更多信息的URL字段的对象。我想将这些字段包装在一个指示它们指向的对象中,所以我创建了一个像这样的对象:
class APIResource<T> {
url: string;
}
T
描述url
应返回的内容。就打字稿而言,T
实际上甚至没有被对象使用,但它帮助我知道我应该期待什么。我正在使用Angular2,但请注意我正在尝试做的不是Angular特定的。我有一个API类,我可以在其中请求URL并提供一个类型将其转换为:
class Person {
name: string;
age: number;
constructor(obj: any) {
// all Constructable<T> classes will
// have a constructor that looks
// exactly like this
Object.assign(this, obj);
}
print() {
console.log(this.name + ' is ' + this.age);
}
}
interface Constructable<T> {
new (obj: any): T;
}
public get<T>(url: string, type: Constructable<T>): Observable<T> {
return this.http.get(url).map(result => {
return new type(result.json());
});
}
基本上,我发一个ajax请求从API获取json,我将它传递给我的类型的构造函数并返回该对象。它会像这样使用:
var person: Person;
api.get('/person/1/', Person).subscribe(p => person = p);
如果我有构造函数要传入,这是有效的,但我想要做的是写一个getResource<T>(resource: APIResource<T>): Observable<T>
函数,这样我就可以这样做:
var res: APIResource<Person> = { url: '/person/1/' };
var person: Person;
api.getResource(res).subscribe(p => person = p);
但到目前为止没有任何效果。现在我无法从T
中获取APIResource
类型来使用我当前的方法。我试过修改APIResource:
class APIResource<T> {
url: string;
getType(): T {
return T;
}
}
或者
class APIResource<T extends Constructable<T>> {
url: string;
fetch(): T {
// just a test to see if tsc complains
// which it does with "cannot find name T"
var obj: any = {};
return new T(obj);
}
}
但它们都不起作用。我知道一旦它是javascript,类型信息就消失了。而不是类型移动,我认为我能够使用移动构造函数,但我不认为我可以使用泛型。
无论如何使用泛型来完成这项工作吗?
我正在使用typescript 1.8.7
答案 0 :(得分:2)
这是在TypeScript中使用泛型来保持强类型的方法:
interface Constructable<T> {
ctor: new (...args) => T;
url: string;
}
class APIResource<T> implements Constructable<T> {
constructor(
public ctor: new (...args) => T,
public url: string
) {}
}
class Person {
name: string;
age: number;
constructor(obj: any) {
//Object.assign(this, obj); // requires ES6
for (var key in obj) this[key] = obj[key];
}
print() {
console.log(`${this.name} is ${this.age}`);
}
}
function getResource<T>(apiResource: APIResource<T>): T {
console.log(`resource url: "${apiResource.url}"`);
// pretend this came back from an ajax request
let obj: any = { name: 'Arthur', age: 42 };
console.log(`obj instanceof Person? ${obj instanceof Person}`); // false
return new apiResource.ctor(obj);
}
const res = new APIResource(Person, '/person/1/');
let person = getResource(res);
console.log(`person instanceof Person? ${person instanceof Person}`); // true
person.print();
我简化了代码,以便它可以在单个自包含的TypeScript文件中运行,以显示这个想法,而不需要Angular 2和rxjs依赖项。但是,将其扩展为Angular 2中的http调用是直截了当的(为清晰起见,将其拆分为多个映射):
getResource<T>(apiResource: APIResource<T>): Observable<T> {
return this.http.get(apiResource.url)
.map(result => result.json())
.map(obj => new apiResource.ctor(obj));
}
然后你可以像往常一样通过subscribe
消费强类型的结果。