Этот тип запроса работал для меня:
db.events.aggregate({$group: {_id : "$date", number: { $sum : 1} }} )
См. http://docs.mongodb.org/manual/tutorial/aggregation-with-user-preference-data/
Вам нужны различные параметры типа для каждого свойства в пути. Это позволяет компилятору рассуждать о конкретных полях, которые вы укажете:
type Props<TState, KStore extends keyof TState, KField extends keyof TState[KStore]> = {
state: KStore;
field: KField
data: TState[KStore][KField]
}
let p: Props<AppState, "cells", "duration"> = {
state: "cells",
field: "duration",
data: 1
}
Причина, по которой вы никогда не получите, заключается в том, что когда компилятор пытается расширить AppState[keyof AppState]
, он получает объединение CellsReducer | BarReducer
. Поскольку доступны только общие члены union keyof (CellsReducer | BarReducer)
- это never
(ключи недоступны).
Дополнительные параметры фиксируют фактическое поле, поэтому, если KStore
является строковым литералом, тип "cells"
keyof AppState["cells"]
будет ключами этого конкретного поля в состоянии приложения. KField
работает аналогично, позволяя нам правильно печатать data
.
Чтобы не указывать значения state
и field
дважды, вы можете написать вспомогательную функцию:
function propertyFactory<TState>() {
return function <KStore extends keyof TState, KField extends keyof TState[KStore]>(o: Props<TState, KStore, KField>) {
return o;
}
}
let p = propertyFactory<AppState>()({
state: "cells",
field: "duration",
data: 1
})
Вы имеете в виду:
interface Props<T, K extends keyof T, V extends keyof T[K]> {
state: keyof T;
field: T[K];
data: T[K][V]
}
Использование:
const props: Props<AppState, 'cells', 'plan'> = { /* ... */ } ;
const props: Props<AppState, 'bar', 'baz'> = { /* ... */ } ;