我有一个模型类,它管理一个内部属性_record
,它是数据库中的记录。模型类是通用基类,每个模型类型都扩展了这个基类。
我想提供两种方便的方法来修改记录中的属性: setValue 用于设置离散数据结构, pushValue 用于将离散数据结构推送到数组上。
/**
* Allows setting individual properties on the record
*
* @param key the property on the record you want to set
* @param value the value of the property
*/
public setValue<K extends keyof T>(key: K, value: T[K]) {
this._record[key] = value;
}
/**
* Allows setting an individual property on a record where the property
* must be an array and result of the operation is the addition
* of a new array element
*
* @param key the property name on the model's record
* @param value an element to add to the existing array
*/
public pushValue<K extends keyof T>(key: K, value: keyof T[K]) {
if (!this._record[key]) {
this._record[key] = [ value ] as T[K];
} else if (Array.isArray(this._record[key])) {
this._record[key] = this._record[key].concat(value);
}
}
setValue
工作正常,但我正在为pushValue
的适当类型进行挣扎。错误是:
我使用的是Typescript 2.4.0
答案 0 :(得分:1)
Array.isArray(this._record[key])
不能用作类型后卫,this._record[key]
仍然在其后输入T[K]
,可能是因为索引属性访问(此处报告了类似问题:https://github.com/Microsoft/TypeScript/issues/11483 ,决议“因性能原因而被拒绝”。)
该问题的建议解决方法是将中间变量而不是this._record[key]
传递给类型保护,它确实有效。对于一个简单变量,其类型推断为const v: T[K] & any[]
,any[]
部分来自Array.isArray
类型后卫,因此此代码使用--noImplicitAny
编译:
abstract class Model<T> {
_record: T;
public setValue<K extends keyof T>(key: K, value: T[K]) {
this._record[key] = value;
}
public pushValue<K extends keyof T, V>(key: K, value: V) {
const v = this._record[key];
if (!v) {
this._record[key] = [value] as any;
} else if (Array.isArray(v)) {
v.push(value);
}
}
}