From d6de40cbe69bf884632b3412b7875fc689665f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 15 Feb 2019 10:49:10 +0100 Subject: [PATCH] Added missing strict type checking options to grafana/ui and fixed type errors --- .../grafana-ui/src/components/Graph/Graph.tsx | 2 +- packages/grafana-ui/src/themes/index.ts | 2 +- .../valueFormats/arithmeticFormatters.ts | 14 ++--- .../utils/valueFormats/dateTimeFormatters.ts | 63 ++++++++++++------- .../utils/valueFormats/symbolFormatters.ts | 4 +- .../src/utils/valueFormats/valueFormats.ts | 47 ++++++++------ packages/grafana-ui/tsconfig.json | 14 ++--- 7 files changed, 85 insertions(+), 61 deletions(-) diff --git a/packages/grafana-ui/src/components/Graph/Graph.tsx b/packages/grafana-ui/src/components/Graph/Graph.tsx index ad038cebcda..d380ad26b68 100644 --- a/packages/grafana-ui/src/components/Graph/Graph.tsx +++ b/packages/grafana-ui/src/components/Graph/Graph.tsx @@ -22,7 +22,7 @@ export class Graph extends PureComponent { showBars: false, }; - element: HTMLElement | null; + element: HTMLElement | null = null; componentDidUpdate() { this.draw(); diff --git a/packages/grafana-ui/src/themes/index.ts b/packages/grafana-ui/src/themes/index.ts index c0d9a4f2d32..1d8d2f62606 100644 --- a/packages/grafana-ui/src/themes/index.ts +++ b/packages/grafana-ui/src/themes/index.ts @@ -6,7 +6,7 @@ let themeMock: ((name?: string) => GrafanaTheme) | null; export let getTheme = (name?: string) => (themeMock && themeMock(name)) || (name === 'light' ? lightTheme : darkTheme); -export const mockTheme = (mock: (name: string) => GrafanaTheme) => { +export const mockTheme = (mock: (name?: string) => GrafanaTheme) => { themeMock = mock; return () => { themeMock = null; diff --git a/packages/grafana-ui/src/utils/valueFormats/arithmeticFormatters.ts b/packages/grafana-ui/src/utils/valueFormats/arithmeticFormatters.ts index fa9daf0fb97..8ff5a1ff5e7 100644 --- a/packages/grafana-ui/src/utils/valueFormats/arithmeticFormatters.ts +++ b/packages/grafana-ui/src/utils/valueFormats/arithmeticFormatters.ts @@ -1,20 +1,20 @@ -import { toFixed } from './valueFormats'; +import { toFixed, DecimalCount } from './valueFormats'; -export function toPercent(size: number, decimals: number) { +export function toPercent(size: number, decimals: DecimalCount) { if (size === null) { return ''; } return toFixed(size, decimals) + '%'; } -export function toPercentUnit(size: number, decimals: number) { +export function toPercentUnit(size: number, decimals: DecimalCount) { if (size === null) { return ''; } return toFixed(100 * size, decimals) + '%'; } -export function toHex0x(value: number, decimals: number) { +export function toHex0x(value: number, decimals: DecimalCount) { if (value == null) { return ''; } @@ -25,7 +25,7 @@ export function toHex0x(value: number, decimals: number) { return '0x' + hexString; } -export function toHex(value: number, decimals: number) { +export function toHex(value: number, decimals: DecimalCount) { if (value == null) { return ''; } @@ -34,9 +34,9 @@ export function toHex(value: number, decimals: number) { .toUpperCase(); } -export function sci(value: number, decimals: number) { +export function sci(value: number, decimals: DecimalCount) { if (value == null) { return ''; } - return value.toExponential(decimals); + return value.toExponential(decimals as number); } diff --git a/packages/grafana-ui/src/utils/valueFormats/dateTimeFormatters.ts b/packages/grafana-ui/src/utils/valueFormats/dateTimeFormatters.ts index 1e07857eb66..819b73586d5 100644 --- a/packages/grafana-ui/src/utils/valueFormats/dateTimeFormatters.ts +++ b/packages/grafana-ui/src/utils/valueFormats/dateTimeFormatters.ts @@ -1,4 +1,4 @@ -import { toFixed, toFixedScaled } from './valueFormats'; +import { toFixed, toFixedScaled, DecimalCount } from './valueFormats'; import moment from 'moment'; interface IntervalsInSeconds { @@ -27,7 +27,7 @@ const INTERVALS_IN_SECONDS: IntervalsInSeconds = { [Interval.Millisecond]: 0.001, }; -export function toNanoSeconds(size: number, decimals: number, scaledDecimals: number) { +export function toNanoSeconds(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) { if (size === null) { return ''; } @@ -45,7 +45,7 @@ export function toNanoSeconds(size: number, decimals: number, scaledDecimals: nu } } -export function toMicroSeconds(size: number, decimals: number, scaledDecimals: number) { +export function toMicroSeconds(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) { if (size === null) { return ''; } @@ -59,7 +59,7 @@ export function toMicroSeconds(size: number, decimals: number, scaledDecimals: n } } -export function toMilliSeconds(size: number, decimals: number, scaledDecimals: number) { +export function toMilliSeconds(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) { if (size === null) { return ''; } @@ -83,22 +83,29 @@ export function toMilliSeconds(size: number, decimals: number, scaledDecimals: n return toFixedScaled(size / 31536000000, decimals, scaledDecimals, 10, ' year'); } -export function toSeconds(size: number, decimals: number, scaledDecimals: number) { +export function trySubstract(value1: DecimalCount, value2: DecimalCount): DecimalCount { + if (value1 !== null && value1 !== undefined && value2 !== null && value2 !== undefined) { + return value1 - value2; + } + return undefined; +} + +export function toSeconds(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) { if (size === null) { return ''; } // Less than 1 µs, divide in ns if (Math.abs(size) < 0.000001) { - return toFixedScaled(size * 1e9, decimals, scaledDecimals - decimals, -9, ' ns'); + return toFixedScaled(size * 1e9, decimals, trySubstract(scaledDecimals, decimals), -9, ' ns'); } // Less than 1 ms, divide in µs if (Math.abs(size) < 0.001) { - return toFixedScaled(size * 1e6, decimals, scaledDecimals - decimals, -6, ' µs'); + return toFixedScaled(size * 1e6, decimals, trySubstract(scaledDecimals, decimals), -6, ' µs'); } // Less than 1 second, divide in ms if (Math.abs(size) < 1) { - return toFixedScaled(size * 1e3, decimals, scaledDecimals - decimals, -3, ' ms'); + return toFixedScaled(size * 1e3, decimals, trySubstract(scaledDecimals, decimals), -3, ' ms'); } if (Math.abs(size) < 60) { @@ -120,7 +127,7 @@ export function toSeconds(size: number, decimals: number, scaledDecimals: number return toFixedScaled(size / 3.15569e7, decimals, scaledDecimals, 7, ' year'); } -export function toMinutes(size: number, decimals: number, scaledDecimals: number) { +export function toMinutes(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) { if (size === null) { return ''; } @@ -138,7 +145,7 @@ export function toMinutes(size: number, decimals: number, scaledDecimals: number } } -export function toHours(size: number, decimals: number, scaledDecimals: number) { +export function toHours(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) { if (size === null) { return ''; } @@ -154,7 +161,7 @@ export function toHours(size: number, decimals: number, scaledDecimals: number) } } -export function toDays(size: number, decimals: number, scaledDecimals: number) { +export function toDays(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) { if (size === null) { return ''; } @@ -168,13 +175,15 @@ export function toDays(size: number, decimals: number, scaledDecimals: number) { } } -export function toDuration(size: number, decimals: number, timeScale: Interval): string { +export function toDuration(size: number, decimals: DecimalCount, timeScale: Interval): string { if (size === null) { return ''; } + if (size === 0) { return '0 ' + timeScale + 's'; } + if (size < 0) { return toDuration(-size, decimals, timeScale) + ' ago'; } @@ -189,14 +198,22 @@ export function toDuration(size: number, decimals: number, timeScale: Interval): { long: Interval.Second }, { long: Interval.Millisecond }, ]; + // convert $size to milliseconds // intervals_in_seconds uses seconds (duh), convert them to milliseconds here to minimize floating point errors size *= INTERVALS_IN_SECONDS[timeScale] * 1000; const strings = []; + // after first value >= 1 print only $decimals more let decrementDecimals = false; - for (let i = 0; i < units.length && decimals >= 0; i++) { + let decimalsCount = 0; + + if (decimals !== null || decimals !== undefined) { + decimalsCount = decimals as number; + } + + for (let i = 0; i < units.length && decimalsCount >= 0; i++) { const interval = INTERVALS_IN_SECONDS[units[i].long] * 1000; const value = size / interval; if (value >= 1 || decrementDecimals) { @@ -205,14 +222,14 @@ export function toDuration(size: number, decimals: number, timeScale: Interval): const unit = units[i].long + (floor !== 1 ? 's' : ''); strings.push(floor + ' ' + unit); size = size % interval; - decimals--; + decimalsCount--; } } return strings.join(', '); } -export function toClock(size: number, decimals?: number) { +export function toClock(size: number, decimals?: DecimalCount) { if (size === null) { return ''; } @@ -257,11 +274,11 @@ export function toClock(size: number, decimals?: number) { return format ? `${hours}:${moment.utc(size).format(format)}` : hours; } -export function toDurationInMilliseconds(size: number, decimals: number) { +export function toDurationInMilliseconds(size: number, decimals: DecimalCount) { return toDuration(size, decimals, Interval.Millisecond); } -export function toDurationInSeconds(size: number, decimals: number) { +export function toDurationInSeconds(size: number, decimals: DecimalCount) { return toDuration(size, decimals, Interval.Second); } @@ -276,19 +293,19 @@ export function toDurationInHoursMinutesSeconds(size: number) { return strings.join(':'); } -export function toTimeTicks(size: number, decimals: number, scaledDecimals: number) { +export function toTimeTicks(size: number, decimals: DecimalCount, scaledDecimals: DecimalCount) { return toSeconds(size, decimals, scaledDecimals); } -export function toClockMilliseconds(size: number, decimals: number) { +export function toClockMilliseconds(size: number, decimals: DecimalCount) { return toClock(size, decimals); } -export function toClockSeconds(size: number, decimals: number) { +export function toClockSeconds(size: number, decimals: DecimalCount) { return toClock(size * 1000, decimals); } -export function dateTimeAsIso(value: number, decimals: number, scaledDecimals: number, isUtc: boolean) { +export function dateTimeAsIso(value: number, decimals: DecimalCount, scaledDecimals: DecimalCount, isUtc?: boolean) { const time = isUtc ? moment.utc(value) : moment(value); if (moment().isSame(value, 'day')) { @@ -297,7 +314,7 @@ export function dateTimeAsIso(value: number, decimals: number, scaledDecimals: n return time.format('YYYY-MM-DD HH:mm:ss'); } -export function dateTimeAsUS(value: number, decimals: number, scaledDecimals: number, isUtc: boolean) { +export function dateTimeAsUS(value: number, decimals: DecimalCount, scaledDecimals: DecimalCount, isUtc?: boolean) { const time = isUtc ? moment.utc(value) : moment(value); if (moment().isSame(value, 'day')) { @@ -306,7 +323,7 @@ export function dateTimeAsUS(value: number, decimals: number, scaledDecimals: nu return time.format('MM/DD/YYYY h:mm:ss a'); } -export function dateTimeFromNow(value: number, decimals: number, scaledDecimals: number, isUtc: boolean) { +export function dateTimeFromNow(value: number, decimals: DecimalCount, scaledDecimals: DecimalCount, isUtc?: boolean) { const time = isUtc ? moment.utc(value) : moment(value); return time.fromNow(); } diff --git a/packages/grafana-ui/src/utils/valueFormats/symbolFormatters.ts b/packages/grafana-ui/src/utils/valueFormats/symbolFormatters.ts index 66808143daa..da8198daf5a 100644 --- a/packages/grafana-ui/src/utils/valueFormats/symbolFormatters.ts +++ b/packages/grafana-ui/src/utils/valueFormats/symbolFormatters.ts @@ -1,9 +1,9 @@ -import { scaledUnits } from './valueFormats'; +import { scaledUnits, DecimalCount } from './valueFormats'; export function currency(symbol: string) { const units = ['', 'K', 'M', 'B', 'T']; const scaler = scaledUnits(1000, units); - return (size: number, decimals: number, scaledDecimals: number) => { + return (size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) => { if (size === null) { return ''; } diff --git a/packages/grafana-ui/src/utils/valueFormats/valueFormats.ts b/packages/grafana-ui/src/utils/valueFormats/valueFormats.ts index 0a56ce58e5b..d626a241a79 100644 --- a/packages/grafana-ui/src/utils/valueFormats/valueFormats.ts +++ b/packages/grafana-ui/src/utils/valueFormats/valueFormats.ts @@ -1,8 +1,15 @@ import { getCategories } from './categories'; -type ValueFormatter = (value: number, decimals?: number, scaledDecimals?: number, isUtc?: boolean) => string; +export type DecimalCount = number | null | undefined; -interface ValueFormat { +export type ValueFormatter = ( + value: number, + decimals?: DecimalCount, + scaledDecimals?: DecimalCount, + isUtc?: boolean +) => string; + +export interface ValueFormat { name: string; id: string; fn: ValueFormatter; @@ -22,7 +29,7 @@ let categories: ValueFormatCategory[] = []; const index: ValueFormatterIndex = {}; let hasBuiltIndex = false; -export function toFixed(value: number, decimals?: number): string { +export function toFixed(value: number, decimals?: DecimalCount): string { if (value === null) { return ''; } @@ -50,20 +57,24 @@ export function toFixed(value: number, decimals?: number): string { export function toFixedScaled( value: number, - decimals: number, - scaledDecimals: number, - additionalDecimals: number, - ext: string + decimals?: DecimalCount, + scaledDecimals?: DecimalCount, + additionalDecimals?: DecimalCount, + ext?: string ) { - if (scaledDecimals === null) { - return toFixed(value, decimals) + ext; - } else { - return toFixed(value, scaledDecimals + additionalDecimals) + ext; + if (scaledDecimals) { + if (additionalDecimals) { + return toFixed(value, scaledDecimals + additionalDecimals) + ext; + } else { + return toFixed(value, scaledDecimals) + ext; + } } + + return toFixed(value, decimals) + ext; } -export function toFixedUnit(unit: string) { - return (size: number, decimals: number) => { +export function toFixedUnit(unit: string): ValueFormatter { + return (size: number, decimals?: DecimalCount) => { if (size === null) { return ''; } @@ -75,7 +86,7 @@ export function toFixedUnit(unit: string) { // numeric factor. Repeatedly scales the value down by the factor until it is // less than the factor in magnitude, or the end of the array is reached. export function scaledUnits(factor: number, extArray: string[]) { - return (size: number, decimals: number, scaledDecimals: number) => { + return (size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) => { if (size === null) { return ''; } @@ -92,7 +103,7 @@ export function scaledUnits(factor: number, extArray: string[]) { } } - if (steps > 0 && scaledDecimals !== null) { + if (steps > 0 && scaledDecimals !== null && scaledDecimals !== undefined) { decimals = scaledDecimals + 3 * steps; } @@ -100,17 +111,17 @@ export function scaledUnits(factor: number, extArray: string[]) { }; } -export function locale(value: number, decimals: number) { +export function locale(value: number, decimals: DecimalCount) { if (value == null) { return ''; } - return value.toLocaleString(undefined, { maximumFractionDigits: decimals }); + return value.toLocaleString(undefined, { maximumFractionDigits: decimals as number }); } export function simpleCountUnit(symbol: string) { const units = ['', 'K', 'M', 'B', 'T']; const scaler = scaledUnits(1000, units); - return (size: number, decimals: number, scaledDecimals: number) => { + return (size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount) => { if (size === null) { return ''; } diff --git a/packages/grafana-ui/tsconfig.json b/packages/grafana-ui/tsconfig.json index 22d336b85f5..1dfe6e0b44c 100644 --- a/packages/grafana-ui/tsconfig.json +++ b/packages/grafana-ui/tsconfig.json @@ -1,21 +1,17 @@ { "extends": "../../tsconfig.json", - "include": [ - "src/**/*.ts", - "src/**/*.tsx" - ], - "exclude": [ - "dist", - "node_modules" - ], + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["dist", "node_modules"], "compilerOptions": { "rootDirs": [".", "stories"], "module": "esnext", "outDir": "dist", "declaration": true, + "strict": true, + "alwaysStrict": true, "noImplicitAny": true, "strictNullChecks": true, "typeRoots": ["./node_modules/@types", "types"], "skipLibCheck": true // Temp workaround for Duplicate identifier tsc errors - }, + } }