Typed variables pt3: Type VariableState with TypedVariableModel (#53015)

* wip

* make diff easier to read

* Update template_srv getVariables to return new TypedVariableModel

* update VariableType to use the type from TypedVariableModel

* tidy things up

* Chore: Use type-accurate mock variables in tests

* Chore: Type VariableState to use TypedVariableModel

* fix typo

* remove type assertion from template_srv.getVariables

* undo whatever changes i did to swagger spec
This commit is contained in:
Josh Hunt 2022-08-03 12:38:59 +01:00 committed by GitHub
parent 8f81c4d2ce
commit c7d3fec515
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 21 deletions

View File

@ -6229,9 +6229,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/variables/state/variablesReducer.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/variables/system/adapter.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],

View File

@ -63,9 +63,7 @@ export class TemplateSrv implements BaseTemplateSrv {
}
getVariables(): TypedVariableModel[] {
// TODO: we remove this type assertion in a later PR
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return this.dependencies.getVariables() as TypedVariableModel[];
return this.dependencies.getVariables();
}
updateIndex() {

View File

@ -1,14 +1,19 @@
import memoizeOne from 'memoize-one';
import { TypedVariableModel, VariableWithMultiSupport, VariableWithOptions } from '@grafana/data';
import { getState } from '../../../store/store';
import { StoreState } from '../../../types';
import { VariableModel } from '../types';
import { toStateKey } from '../utils';
import { getInitialTemplatingState, TemplatingState } from './reducers';
import { KeyedVariableIdentifier, VariablesState } from './types';
export const getVariable = <T extends VariableModel = VariableModel>(
// TODO: this is just a temporary type until we remove generics from getVariable and getInstanceState in a later PR
// we need to it satisfy the constraint of callers who specify VariableWithOptions or VariableWithMultiSupport
type GenericVariableModel = TypedVariableModel | VariableWithOptions | VariableWithMultiSupport;
export const getVariable = <T extends GenericVariableModel = GenericVariableModel>(
identifier: KeyedVariableIdentifier,
state: StoreState = getState(),
throwWhenMissing = true
@ -26,7 +31,7 @@ export const getVariable = <T extends VariableModel = VariableModel>(
};
function getFilteredVariablesByKey(
filter: (model: VariableModel) => boolean,
filter: (model: TypedVariableModel) => boolean,
key: string,
state: StoreState = getState()
) {
@ -39,21 +44,21 @@ export function getVariablesState(key: string, state: StoreState = getState()):
return state.templating.keys[toStateKey(key)] ?? getInitialTemplatingState();
}
export function getVariablesByKey(key: string, state: StoreState = getState()): VariableModel[] {
export function getVariablesByKey(key: string, state: StoreState = getState()): TypedVariableModel[] {
return getFilteredVariablesByKey(defaultVariablesFilter, key, state);
}
function defaultVariablesFilter(variable: VariableModel): boolean {
function defaultVariablesFilter(variable: TypedVariableModel): boolean {
return variable.type !== 'system';
}
export const getSubMenuVariables = memoizeOne(
(key: string, variables: Record<string, VariableModel>): VariableModel[] => {
(key: string, variables: Record<string, TypedVariableModel>): TypedVariableModel[] => {
return getVariablesByKey(key, getState());
}
);
export const getEditorVariables = (key: string, state: StoreState): VariableModel[] => {
export const getEditorVariables = (key: string, state: StoreState): TypedVariableModel[] => {
return getVariablesByKey(key, state);
};
@ -63,7 +68,7 @@ export function getNewVariableIndex(key: string, state: StoreState = getState())
return getNextVariableIndex(Object.values(getVariablesState(key, state).variables));
}
export function getNextVariableIndex(variables: VariableModel[]): number {
export function getNextVariableIndex(variables: TypedVariableModel[]): number {
const sorted = variables.filter(defaultVariablesFilter).sort((v1, v2) => v1.index - v2.index);
return sorted.length > 0 ? sorted[sorted.length - 1].index + 1 : 0;
}
@ -85,7 +90,7 @@ export function getLastKey(state: StoreState = getState()): string {
}
// selectors used by template srv, assumes that lastKey is in state. Needs to change when/if dashboard redux state becomes keyed too.
export function getFilteredVariables(filter: (model: VariableModel) => boolean, state: StoreState = getState()) {
export function getFilteredVariables(filter: (model: TypedVariableModel) => boolean, state: StoreState = getState()) {
const lastKey = getIfExistsLastKey(state);
if (!lastKey) {
return [];
@ -109,6 +114,10 @@ export function getVariableWithName(name: string, state: StoreState = getState()
return getVariable({ id: name, rootStateKey: lastKey, type: 'query' }, state, false);
}
export function getInstanceState<Model extends VariableModel = VariableModel>(state: VariablesState, id: string) {
// TODO: remove the generic and type assertion in a later PR
export function getInstanceState<Model extends GenericVariableModel = GenericVariableModel>(
state: VariablesState,
id: string
) {
return state[id] as Model;
}

View File

@ -1,8 +1,8 @@
import { VariableType } from '@grafana/data';
import { VariableType, TypedVariableModel } from '@grafana/data';
import { VariableModel } from '../types';
export interface VariablesState extends Record<string, VariableModel> {}
export type VariablesState = Record<string, TypedVariableModel>;
export const initialVariablesState: VariablesState = {};

View File

@ -2,7 +2,6 @@ import { createAction } from '@reduxjs/toolkit';
import { AnyAction } from 'redux';
import { variableAdapters } from '../adapters';
import { VariableModel } from '../types';
import { sharedReducer } from './sharedReducer';
import { initialVariablesState, VariablesState } from './types';
@ -16,10 +15,10 @@ export const variablesReducer = (state: VariablesState = initialVariablesState,
return initialVariablesState;
}
const variables = globalVariables.reduce((allVariables, state) => {
const variables = globalVariables.reduce<typeof state>((allVariables, state) => {
allVariables[state.id] = state;
return allVariables;
}, {} as Record<string, VariableModel>);
}, {});
return variables;
}