diff --git a/packages/event-processor/__tests__/pendingEventsStore.spec.ts b/packages/event-processor/__tests__/pendingEventsStore.spec.ts index 23a8b4871..780b5ae13 100644 --- a/packages/event-processor/__tests__/pendingEventsStore.spec.ts +++ b/packages/event-processor/__tests__/pendingEventsStore.spec.ts @@ -93,7 +93,7 @@ describe('LocalStorageStore', () => { { uuid: '3', timestamp: 3, value: 'third' }, ]) - const newMap = {} + const newMap: { [key: string]: TestEntry } = {} store.values().forEach(item => { newMap[item.uuid] = { ...item, diff --git a/packages/logging/src/logger.ts b/packages/logging/src/logger.ts index 269968372..5da90e493 100644 --- a/packages/logging/src/logger.ts +++ b/packages/logging/src/logger.ts @@ -18,7 +18,15 @@ import { isValidEnum, sprintf } from '@optimizely/js-sdk-utils' import { LogLevel, LoggerFacade, LogManager, LogHandler } from './models' -const stringToLogLevel = { +type StringToLogLevel = { + NOTSET: number, + DEBUG: number, + INFO: number, + WARNING: number, + ERROR: number, +} + +const stringToLogLevel: StringToLogLevel = { NOTSET: 0, DEBUG: 1, INFO: 2, @@ -36,11 +44,11 @@ function coerceLogLevel(level: any): LogLevel { level = 'WARNING' } - if (!stringToLogLevel[level]) { + if (!stringToLogLevel[level as keyof StringToLogLevel]) { return level } - return stringToLogLevel[level] + return stringToLogLevel[level as keyof StringToLogLevel] } type LogData = { diff --git a/packages/optimizely-sdk/lib/optimizely/index.ts b/packages/optimizely-sdk/lib/optimizely/index.ts index e477cd351..d71db9cbc 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.ts +++ b/packages/optimizely-sdk/lib/optimizely/index.ts @@ -78,6 +78,11 @@ export interface OptimizelyOptions { userProfileService?: UserProfileService | null; } +// TODO: Make feature_key, user_id, variable_key, experiment_key, event_key camelCase +export type InputKey = 'feature_key' | 'user_id' | 'variable_key' | 'experiment_key' | 'event_key' | 'variation_id'; + +export type StringInputs = Partial>; + /** * The Optimizely class * @param {OptimizelyOptions} config @@ -581,15 +586,14 @@ export default class Optimizely { /** * Validate string inputs, user attributes and event tags. - * @param {unknown} stringInputs Map of string keys and associated values - * @param {unknown} userAttributes Optional parameter for user's attributes - * @param {unknown} eventTags Optional parameter for event tags - * @return {boolean} True if inputs are valid + * @param {StringInputs} stringInputs Map of string keys and associated values + * @param {unknown} userAttributes Optional parameter for user's attributes + * @param {unknown} eventTags Optional parameter for event tags + * @return {boolean} True if inputs are valid * */ private validateInputs( - // TODO: Make feature_key, user_id, variable_key, experiment_key camelCase - stringInputs: Partial>, + stringInputs: StringInputs, userAttributes?: unknown, eventTags?: unknown ): boolean { @@ -603,7 +607,7 @@ export default class Optimizely { delete stringInputs['user_id']; } Object.keys(stringInputs).forEach(key => { - if (!stringValidator.validate(stringInputs[key])) { + if (!stringValidator.validate(stringInputs[key as InputKey])) { throw new Error(sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, MODULE_NAME, key)); } }) @@ -1196,7 +1200,7 @@ export default class Optimizely { const decisionObj = this.decisionService.getVariationForFeature(configObj, featureFlag, userId, attributes); const featureEnabled = decision.getFeatureEnabledFromVariation(decisionObj); - const allVariables = {}; + const allVariables: { [variableKey: string]: unknown } = {}; featureFlag.variables.forEach((variable: FeatureVariable) => { allVariables[variable.key] = this.getFeatureVariableValueFromVariation(featureKey, featureEnabled, decisionObj.variation, variable, userId); diff --git a/packages/optimizely-sdk/lib/shared_types.ts b/packages/optimizely-sdk/lib/shared_types.ts index 3ec5e3ee4..31423ba34 100644 --- a/packages/optimizely-sdk/lib/shared_types.ts +++ b/packages/optimizely-sdk/lib/shared_types.ts @@ -11,7 +11,7 @@ export interface UserProfile { user_id: string; experiment_bucket_map: { [experiment_id: string]: { - variation_id: string; + variation_id: string; }; }; } @@ -71,7 +71,7 @@ export interface Variation { export interface Experiment { id: string; key: string; - variationKeyMap: {[key: string]: Variation} + variationKeyMap: { [key: string]: Variation } } export interface FeatureVariable { @@ -87,7 +87,7 @@ export interface FeatureFlag { id: string; experimentIds: string[], variables: FeatureVariable[], - variableKeyMap: {[key: string]: FeatureVariable} + variableKeyMap: { [key: string]: FeatureVariable } } export interface FeatureKeyMap { @@ -99,6 +99,10 @@ export interface OnReadyResult { reason?: string; } +export type ObjectWithUnknownProperties = { + [key: string]: unknown; +} + /** * Optimizely Config Entities */ diff --git a/packages/optimizely-sdk/lib/utils/attributes_validator/index.ts b/packages/optimizely-sdk/lib/utils/attributes_validator/index.ts index 8fdccbe50..e3c475390 100644 --- a/packages/optimizely-sdk/lib/utils/attributes_validator/index.ts +++ b/packages/optimizely-sdk/lib/utils/attributes_validator/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { sprintf } from '@optimizely/js-sdk-utils'; +import { ObjectWithUnknownProperties } from '../../shared_types'; import fns from '../../utils/fns'; import { ERROR_MESSAGES } from '../enums'; @@ -30,7 +31,7 @@ const MODULE_NAME = 'ATTRIBUTES_VALIDATOR'; export function validate(attributes: unknown): boolean { if (typeof attributes === 'object' && !Array.isArray(attributes) && attributes !== null) { Object.keys(attributes).forEach(function(key) { - if (typeof attributes[key] === 'undefined') { + if (typeof (attributes as ObjectWithUnknownProperties)[key] === 'undefined') { throw new Error(sprintf(ERROR_MESSAGES.UNDEFINED_ATTRIBUTE, MODULE_NAME, key)); } }); diff --git a/packages/optimizely-sdk/lib/utils/config_validator/index.ts b/packages/optimizely-sdk/lib/utils/config_validator/index.ts index d71841581..ef156555a 100644 --- a/packages/optimizely-sdk/lib/utils/config_validator/index.ts +++ b/packages/optimizely-sdk/lib/utils/config_validator/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { sprintf } from '@optimizely/js-sdk-utils'; +import { ObjectWithUnknownProperties } from '../../shared_types'; import { ERROR_MESSAGES, @@ -34,13 +35,17 @@ const SUPPORTED_VERSIONS = [DATAFILE_VERSIONS.V2, DATAFILE_VERSIONS.V3, DATAFILE */ export const validate = function(config: unknown): boolean { if (typeof config === 'object' && config !== null) { - if (config['errorHandler'] && typeof config['errorHandler'].handleError !== 'function') { + const configObj = config as ObjectWithUnknownProperties; + const errorHandler = configObj['errorHandler']; + const eventDispatcher = configObj['eventDispatcher']; + const logger = configObj['logger']; + if (errorHandler && typeof (errorHandler as ObjectWithUnknownProperties)['handleError'] !== 'function') { throw new Error(sprintf(ERROR_MESSAGES.INVALID_ERROR_HANDLER, MODULE_NAME)); } - if (config['eventDispatcher'] && typeof config['eventDispatcher'].dispatchEvent !== 'function') { + if (eventDispatcher && typeof (eventDispatcher as ObjectWithUnknownProperties)['dispatchEvent'] !== 'function') { throw new Error(sprintf(ERROR_MESSAGES.INVALID_EVENT_DISPATCHER, MODULE_NAME)); } - if (config['logger'] && typeof config['logger'].log !== 'function') { + if (logger && typeof (logger as ObjectWithUnknownProperties)['log'] !== 'function') { throw new Error(sprintf(ERROR_MESSAGES.INVALID_LOGGER, MODULE_NAME)); } return true; @@ -71,8 +76,8 @@ export const validateDatafile = function(datafile: unknown): any { } } if (typeof datafile === 'object' && !Array.isArray(datafile) && datafile !== null) { - if (SUPPORTED_VERSIONS.indexOf(datafile['version']) === -1) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_DATAFILE_VERSION, MODULE_NAME, datafile['version'])); + if (SUPPORTED_VERSIONS.indexOf(datafile['version' as keyof unknown]) === -1) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_DATAFILE_VERSION, MODULE_NAME, datafile['version' as keyof unknown])); } } diff --git a/packages/optimizely-sdk/lib/utils/fns/index.ts b/packages/optimizely-sdk/lib/utils/fns/index.ts index e2e5800f6..59be164a9 100644 --- a/packages/optimizely-sdk/lib/utils/fns/index.ts +++ b/packages/optimizely-sdk/lib/utils/fns/index.ts @@ -52,7 +52,8 @@ function isSafeInteger(number: unknown): boolean { function keyBy(arr: K[], key: string): { [key: string]: K } { if (!arr) return {}; return keyByUtil(arr, function (item) { - return item[key]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (item as any)[key]; }); } diff --git a/packages/optimizely-sdk/lib/utils/user_profile_service_validator/index.ts b/packages/optimizely-sdk/lib/utils/user_profile_service_validator/index.ts index 9c264178e..ea59c8220 100644 --- a/packages/optimizely-sdk/lib/utils/user_profile_service_validator/index.ts +++ b/packages/optimizely-sdk/lib/utils/user_profile_service_validator/index.ts @@ -19,6 +19,7 @@ */ import { sprintf } from '@optimizely/js-sdk-utils'; +import { ObjectWithUnknownProperties } from '../../shared_types'; import { ERROR_MESSAGES } from '../enums'; @@ -33,9 +34,9 @@ const MODULE_NAME = 'USER_PROFILE_SERVICE_VALIDATOR'; export function validate(userProfileServiceInstance: unknown): boolean { if (typeof userProfileServiceInstance === 'object' && userProfileServiceInstance !== null) { - if (typeof userProfileServiceInstance['lookup'] !== 'function') { + if (typeof (userProfileServiceInstance as ObjectWithUnknownProperties)['lookup'] !== 'function') { throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'lookup'")); - } else if (typeof userProfileServiceInstance['save'] !== 'function') { + } else if (typeof (userProfileServiceInstance as ObjectWithUnknownProperties)['save'] !== 'function') { throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'save'")); } return true; diff --git a/tsconfig.json b/tsconfig.json index 000ff9c89..1073836e9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,6 @@ // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ - "suppressImplicitAnyIndexErrors": true, // "importHelpers": true /* Import emit helpers from 'tslib'. */, // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */