问题描述
在getValue
类的DataBankService
方法下面的代码中,丢失了类型信息(请参见示例)。是否可以保留类型信息?
https://stackblitz.com/edit/typescript-rx-playground-gqnzuq?file=index.ts
import { Subject } from "rxjs/";
export interface DataObject<T> {
value: T;
observable: Subject<T>;
}
export class DataBankService {
private dataBank: DataBankProperties;
constructor() {
this.dataBank = new DataBankProperties();
}
public getValue<T extends keyof DataBankProperties,V>(property: T) {
return this.dataBank[property].value;
}
}
class DataBankProperties {
money: DataObject<number> = this.createDataObject();
token: DataObject<string> = this.createDataObject();
testament: DataObject<object> = this.createDataObject();
private createDataObject<T>() {
return {
value: null,observable: new Subject<T>(),};
}
}
const dataBank = new DataBankService();
// token is Now type >> token: string | number | object
const token = dataBank.getValue('token');
// I would like this to be type string
// token is Now type >> token: string | number | object
const money = dataBank.getValue('money');
// I would like this to be type number
解决方法
您可以在返回类型上使用断言来执行此操作-将泛型用作DataBankProperties的键。我已将其重命名为K以表示约定(如K表示密钥)
public getValue<K extends keyof DataBankProperties>(property: K): DataBankProperties[K]['value'] {
return this.dataBank[property].value;
}
,
我建议创建一个类型来推断DataObject的通用类型:
type DataObjectTypeInference<T> = T extends DataObject<infer U> ? U : never;
然后像这样使用它:
public getValue<K extends keyof DataBankProperties>(property: K) {
return this.dataBank[property].value as DataObjectTypeInference<
DataBankProperties[T]
>;
}
首先,定义一个类型,该类型将照顾当前类型实例的DataObject的通用类型。我个人更希望不要在属性名称之间加上任何文字,也不要喜欢我之前的评论。我希望它是由TypeScript推断的,因此,如果您决定将value键更改为另一个名称,则不会影响类型推断。
然后,将变量的类型声明为DataBankProperties [T],它为您提供DataObject的类型,现在您使用我们构建的类型并推断出DataObject的通用类型。