I'm trying to 'denormalize' two arrays (IObservableArray and IObservableArray) where array A has objects with id's that point to id's of objects in array B. I would like to put objects from array B that match the id of the object in array A on object A as a dynamically named property. The arrays are IObservableArray
s from mobx
but that should not be of importance.
I'm trying to achieve this:
var aArr: IObservableArray<A extends { bId: number }>;
var bArr: IObservableArray<B extends { id: number }>;
var d = denormalize(aArr, bArr, (a, b) => a.bId === b.id, "b");
console.log(d[0].b) // => B
I tried the following:
export function denormalize<A, B, K extends string, TRet extends A & {[asProperty: K]: B}>(
arr1: IObservableArray<A>,
arr2: IObservableArray<B>,
where: (a: A, b: B) => boolean,
asProperty: K
): IObservableArray<TRet> {
return observable.array(); // stub
}
But it says [ts] An index signature parameter type must be 'string' or 'number'.
(parameter) k: K extends string
Is there a way to make the A[asProperty]: B
work so that the compiler knows that the type returned by denormalize
has an additional property with name asProperty
and it autocompletes as such?
答案 0 :(得分:2)
您不能在索引签名中使用泛型类型,索引器参数必须为string
或number
(这取决于spec)。
您可以使用映射类型语法([Prop in Key] : Type
)
export function denormalize<A, B, K extends string, TRet extends A & { [P in K]: B}>(
arr1: IObservableArray<A>,
arr2: IObservableArray<B>,
where: (a: A, b: B) => boolean,
asProperty: K
): IObservableArray<TRet> {
// ...
}
会工作:
console.log(d[0].b) // => B
修改
正如@jcalz在评论中提到的,签名也可以使用与Record<K extends string, T>
相同的{ [P in K]: B}>
类型。使用此签名将是:
export function denormalize<A, B, K extends string, TRet extends A & Record<K,B>>(
arr1: IObservableArray<A>,
arr2: IObservableArray<B>,
where: (a: A, b: B) => boolean,
asProperty: K
): IObservableArray<TRet>