From bc1bf926da948be746e4338e1bc2159d329c7345 Mon Sep 17 00:00:00 2001 From: Nishant Mittal Date: Thu, 2 Jul 2020 02:01:02 +0530 Subject: [PATCH 1/2] Remove some more any types --- .../oppia-angular-root.component.ts | 6 -- .../state-content.service.ts | 3 +- .../state-customization-args.service.ts | 5 +- .../state-hints.service.spec.ts | 20 ++-- .../state-hints.service.ts | 5 +- .../state-interaction-id.service.ts | 2 +- .../state-param-changes.service.ts | 4 +- .../state-property.service.ts | 45 ++++----- .../state-recorded-voiceovers.service.ts | 5 +- .../state-solicit-answer-details.service.ts | 3 +- .../state-solution.service.ts | 3 +- .../state-written-translations.service.ts | 5 +- ...AnswerClassificationResultObjectFactory.ts | 14 +-- ...erClassificationResultObjectFactorySpec.ts | 56 ++--------- .../exploration/ExplorationObjectFactory.ts | 94 ++++++++++++------- .../exploration/ParamSpecsObjectFactory.ts | 2 +- .../domain/exploration/StatesObjectFactory.ts | 43 +++++---- .../FeedbackThreadObjectFactory.ts | 2 +- .../domain/state/StateObjectFactory.ts | 2 +- .../LearnerAnswerDetailsObjectFactory.ts | 8 +- .../suggestion/SuggestionObjectFactory.ts | 2 +- ...ate-improvement-suggestion.service.spec.ts | 73 +++++++++++--- .../templates/services/suggestions.service.ts | 7 +- scripts/linters/excluded_any_type_files.json | 8 -- 24 files changed, 225 insertions(+), 192 deletions(-) diff --git a/core/templates/components/oppia-angular-root.component.ts b/core/templates/components/oppia-angular-root.component.ts index de6f74d23d40..2a81879cd5e1 100644 --- a/core/templates/components/oppia-angular-root.component.ts +++ b/core/templates/components/oppia-angular-root.component.ts @@ -496,9 +496,6 @@ import { StateObjectFactory } from 'domain/state/StateObjectFactory'; import { StateParamChangesService } from // eslint-disable-next-line max-len 'components/state-editor/state-editor-properties-services/state-param-changes.service'; -import { StatePropertyService } from - // eslint-disable-next-line max-len - 'components/state-editor/state-editor-properties-services/state-property.service'; import { StateRecordedVoiceoversService } from // eslint-disable-next-line max-len 'components/state-editor/state-editor-properties-services/state-recorded-voiceovers.service'; @@ -842,7 +839,6 @@ export class OppiaAngularRootComponent implements AfterViewInit { static stateNameService: StateNameService; static stateObjectFactory: StateObjectFactory; static stateParamChangesService: StateParamChangesService; - static statePropertyService: StatePropertyService; static stateRecordedVoiceoversService: StateRecordedVoiceoversService; static stateSolicitAnswerDetailsService: StateSolicitAnswerDetailsService; static stateSolutionService: StateSolutionService; @@ -1126,7 +1122,6 @@ private stateInteractionStatsService: StateInteractionStatsService, private stateNameService: StateNameService, private stateObjectFactory: StateObjectFactory, private stateParamChangesService: StateParamChangesService, -private statePropertyService: StatePropertyService, private stateRecordedVoiceoversService: StateRecordedVoiceoversService, private stateSolicitAnswerDetailsService: StateSolicitAnswerDetailsService, private stateSolutionService: StateSolutionService, @@ -1411,7 +1406,6 @@ private writtenTranslationsObjectFactory: WrittenTranslationsObjectFactory OppiaAngularRootComponent.stateNameService = this.stateNameService; OppiaAngularRootComponent.stateObjectFactory = this.stateObjectFactory; OppiaAngularRootComponent.stateParamChangesService = this.stateParamChangesService; - OppiaAngularRootComponent.statePropertyService = this.statePropertyService; OppiaAngularRootComponent.stateRecordedVoiceoversService = this.stateRecordedVoiceoversService; OppiaAngularRootComponent.stateSolicitAnswerDetailsService = this.stateSolicitAnswerDetailsService; OppiaAngularRootComponent.stateSolutionService = this.stateSolutionService; diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-content.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-content.service.ts index 3b728f2e5f4a..ed473805eb95 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-content.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-content.service.ts @@ -23,12 +23,13 @@ import { StatePropertyService } from // eslint-disable-next-line max-len 'components/state-editor/state-editor-properties-services/state-property.service'; import { UtilsService } from 'services/utils.service'; +import { SubtitledHtml } from 'domain/exploration/SubtitledHtmlObjectFactory'; @Injectable({ providedIn: 'root' }) // TODO(sll): Add validation. -export class StateContentService extends StatePropertyService { +export class StateContentService extends StatePropertyService { constructor(alertsService: AlertsService, utilsService: UtilsService) { super(alertsService, utilsService); this.setterMethodKey = 'saveStateContent'; diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-customization-args.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-customization-args.service.ts index 506c5f8f9fdb..6f6b7c27e634 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-customization-args.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-customization-args.service.ts @@ -25,12 +25,15 @@ import { StatePropertyService } from // eslint-disable-next-line max-len 'components/state-editor/state-editor-properties-services/state-property.service'; import { UtilsService } from 'services/utils.service'; +import { IInteractionCustomizationArgs } from + 'interactions/customization-args-defs'; @Injectable({ providedIn: 'root' }) // TODO(sll): Add validation. -export class StateCustomizationArgsService extends StatePropertyService { +export class StateCustomizationArgsService extends + StatePropertyService { constructor(alertsService: AlertsService, utilsService: UtilsService) { super(alertsService, utilsService); this.setterMethodKey = 'saveInteractionCustomizationArgs'; diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.spec.ts b/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.spec.ts index a09ea81b23e8..7459143e7419 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.spec.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.spec.ts @@ -17,23 +17,22 @@ */ import { TestBed } from '@angular/core/testing'; -import { UtilsService } from 'services/utils.service'; -import { AlertsService } from 'services/alerts.service'; +import { HintObjectFactory } from 'domain/exploration/HintObjectFactory'; /* eslint-disable max-len */ import { StateHintsService } from 'components/state-editor/state-editor-properties-services/state-hints.service'; /* eslint-disable max-len */ describe('State hints service', () => { let shs: StateHintsService = null; - let alertsService : AlertsService; - let utilsService : UtilsService; + let hof: HintObjectFactory = null; beforeEach(() => { TestBed.configureTestingModule({ - providers: [StateHintsService] + providers: [StateHintsService, HintObjectFactory] }); shs = TestBed.get(StateHintsService); + hof = TestBed.get(HintObjectFactory); }); it('should called the constructor', () =>{ @@ -43,11 +42,12 @@ describe('State hints service', () => { it('should called setActiveHintIndex after init', () =>{ spyOn(shs, 'setActiveHintIndex'); const StateName = 'Introduction'; - const value = {0: { - _html: '

math

', - _contentId: 'hint_1' - } - }; + const value = [{ + hint_content: { + html: '

math

', + content_id: 'hint_1' + } + }].map(hof.createFromBackendDict); shs.init(StateName, value); expect(shs.setActiveHintIndex).toHaveBeenCalled(); }); diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.ts index fe02fc1a30da..c2fa062f89cd 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.ts @@ -19,6 +19,7 @@ import { downgradeInjectable } from '@angular/upgrade/static'; import { Injectable } from '@angular/core'; import { AlertsService } from 'services/alerts.service'; +import { Hint } from 'domain/exploration/HintObjectFactory'; import { StatePropertyService } from // eslint-disable-next-line max-len 'components/state-editor/state-editor-properties-services/state-property.service'; @@ -27,7 +28,7 @@ import { UtilsService } from 'services/utils.service'; @Injectable({ providedIn: 'root' }) -export class StateHintsService extends StatePropertyService { +export class StateHintsService extends StatePropertyService { private activeHintIndex: number; constructor(alertsService: AlertsService, utilsService: UtilsService) { super(alertsService, utilsService); @@ -42,7 +43,7 @@ export class StateHintsService extends StatePropertyService { this.activeHintIndex = index; } - init(stateName: string, value: any): void { + init(stateName: string, value: Hint[]): void { super.init(stateName, value); this.setActiveHintIndex(null); } diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-interaction-id.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-interaction-id.service.ts index 0ee0ba319de7..5b8c3a23ac27 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-interaction-id.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-interaction-id.service.ts @@ -28,7 +28,7 @@ import { UtilsService } from 'services/utils.service'; providedIn: 'root' }) // TODO(sll): Add validation. -export class StateInteractionIdService extends StatePropertyService { +export class StateInteractionIdService extends StatePropertyService { constructor(alertsService: AlertsService, utilsService: UtilsService) { super(alertsService, utilsService); this.setterMethodKey = 'saveInteractionId'; diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-param-changes.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-param-changes.service.ts index d543890a79ed..73274c4b487c 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-param-changes.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-param-changes.service.ts @@ -20,6 +20,7 @@ import { downgradeInjectable } from '@angular/upgrade/static'; import { Injectable } from '@angular/core'; import { AlertsService } from 'services/alerts.service'; +import { ParamChange } from 'domain/exploration/ParamChangeObjectFactory'; import { StatePropertyService } from // eslint-disable-next-line max-len 'components/state-editor/state-editor-properties-services/state-property.service'; @@ -29,7 +30,8 @@ import { UtilsService } from 'services/utils.service'; providedIn: 'root' }) // TODO(sll): Add validation. -export class StateParamChangesService extends StatePropertyService { +export class StateParamChangesService extends + StatePropertyService { constructor(alertsService: AlertsService, utilsService: UtilsService) { super(alertsService, utilsService); this.setterMethodKey = 'saveStateParamChanges'; diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-property.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-property.service.ts index ae888d6b12c8..200650ba2342 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-property.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-property.service.ts @@ -24,35 +24,36 @@ import cloneDeep from 'lodash/cloneDeep'; import { AlertsService } from 'services/alerts.service'; import { UtilsService } from 'services/utils.service'; +/** + * NOTE TO DEVELOPERS: This class should not be used to create objects directly. + * This class should be first inherited to a other class. And a type argument + * with the type of state property should be passed. + * + * Example usage: + * class ExampleClass extends StatePropertyService { + * ... + * } + * + * This will initialize the class with the type of properties like displayed, + * savedMomento etc. to be string. + */ @Injectable({ providedIn: 'root' }) -export class StatePropertyService { +export class StatePropertyService { // The name of the setter method in ExplorationStatesService for this // property. THIS MUST BE SPECIFIED BY SUBCLASSES. setterMethodKey: string; - // TODO(#7165): Replace 'any' with the exact type. This has been kept - // as any since type of displayed depends on the property for which the - // value is provided. We need to create different domain objects for - // various properties and decide type of displayed according to that. - displayed: any; + displayed: StatePropertyType; stateName: string; - // TODO(#7165): Replace 'any' with the exact type. This has been kept - // as any since type of savedMemento depends on the property for which the - // value is provided. We need to create different domain objects for - // various properties and decide type of savedMemento according to that. - savedMemento: any; + savedMemento: StatePropertyType; constructor(private alertsService: AlertsService, private utilsService: UtilsService) { this.setterMethodKey = null; } - // TODO(#7165): Replace 'any' with the exact type. This has been kept - // as any since type of value depends on the property for which the - // value is provided. We need to create different domain objects for - // various properties and decide type of value according to that. - init(stateName: string, value: any): void { + init(stateName: string, value: StatePropertyType): void { if (this.setterMethodKey === null) { throw new Error('State property setter method key cannot be null.'); } @@ -74,22 +75,14 @@ export class StatePropertyService { // Transforms the given value into a normalized form. THIS CAN BE // OVERRIDDEN BY SUBCLASSES. The default behavior is to do nothing. - // TODO(#7165): Replace 'any' with the exact type. This has been kept - // as any since type of value depends on the property for which the - // value is provided. We need to create different domain objects for - // various properties and decide type of value according to that. - _normalize(value: any): any { + _normalize(value: StatePropertyType): StatePropertyType { return value; } // Validates the given value and returns a boolean stating whether it // is valid or not. THIS CAN BE OVERRIDDEN BY SUBCLASSES. The default // behavior is to always return true. - // TODO(#7165): Replace 'any' with the exact type. This has been kept - // as any since type of value depends on the property for which the - // value is provided. We need to create different domain objects for - // various properties and decide type of value according to that. - _isValid(value: any): boolean { + _isValid(value: StatePropertyType): boolean { return true; } diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-recorded-voiceovers.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-recorded-voiceovers.service.ts index 56381c409ca7..b987211802ef 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-recorded-voiceovers.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-recorded-voiceovers.service.ts @@ -23,12 +23,15 @@ import { AlertsService } from 'services/alerts.service'; import { StatePropertyService } from // eslint-disable-next-line max-len 'components/state-editor/state-editor-properties-services/state-property.service'; +import { RecordedVoiceovers } from + 'domain/exploration/RecordedVoiceoversObjectFactory'; import { UtilsService } from 'services/utils.service'; @Injectable({ providedIn: 'root' }) -export class StateRecordedVoiceoversService extends StatePropertyService { +export class StateRecordedVoiceoversService extends + StatePropertyService { constructor(alertsService: AlertsService, utilsService: UtilsService) { super(alertsService, utilsService); this.setterMethodKey = 'saveRecordedVoiceovers'; diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-solicit-answer-details.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-solicit-answer-details.service.ts index 2362d278bb82..74eea1445459 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-solicit-answer-details.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-solicit-answer-details.service.ts @@ -27,7 +27,8 @@ import { UtilsService } from 'services/utils.service'; @Injectable({ providedIn: 'root' }) -export class StateSolicitAnswerDetailsService extends StatePropertyService { +export class StateSolicitAnswerDetailsService extends + StatePropertyService { constructor(alertsService: AlertsService, utilsService: UtilsService) { super(alertsService, utilsService); this.setterMethodKey = 'saveSolicitAnswerDetails'; diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-solution.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-solution.service.ts index a1710c5dee8f..f99b8e0c4a41 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-solution.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-solution.service.ts @@ -19,6 +19,7 @@ import { downgradeInjectable } from '@angular/upgrade/static'; import { Injectable } from '@angular/core'; import { AlertsService } from 'services/alerts.service'; +import { Solution } from 'domain/exploration/SolutionObjectFactory'; import { StatePropertyService } from // eslint-disable-next-line max-len 'components/state-editor/state-editor-properties-services/state-property.service'; @@ -27,7 +28,7 @@ import { UtilsService } from 'services/utils.service'; @Injectable({ providedIn: 'root' }) -export class StateSolutionService extends StatePropertyService { +export class StateSolutionService extends StatePropertyService { constructor(alertsService: AlertsService, utilsService: UtilsService) { super(alertsService, utilsService); this.setterMethodKey = 'saveSolution'; diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-written-translations.service.ts b/core/templates/components/state-editor/state-editor-properties-services/state-written-translations.service.ts index 2885880865de..ec0774ec6b0e 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-written-translations.service.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-written-translations.service.ts @@ -23,11 +23,14 @@ import { StatePropertyService } from // eslint-disable-next-line max-len 'components/state-editor/state-editor-properties-services/state-property.service'; import { UtilsService } from 'services/utils.service'; +import { WrittenTranslations } from + 'domain/exploration/WrittenTranslationsObjectFactory'; @Injectable({ providedIn: 'root' }) -export class StateWrittenTranslationsService extends StatePropertyService { +export class StateWrittenTranslationsService extends + StatePropertyService { constructor(alertsService: AlertsService, utilsService: UtilsService) { super(alertsService, utilsService); this.setterMethodKey = 'saveWrittenTranslations'; diff --git a/core/templates/domain/classifier/AnswerClassificationResultObjectFactory.ts b/core/templates/domain/classifier/AnswerClassificationResultObjectFactory.ts index 097e3a9436fd..8196b34e6605 100644 --- a/core/templates/domain/classifier/AnswerClassificationResultObjectFactory.ts +++ b/core/templates/domain/classifier/AnswerClassificationResultObjectFactory.ts @@ -20,17 +20,16 @@ import { downgradeInjectable } from '@angular/upgrade/static'; import { Injectable } from '@angular/core'; +import { Outcome } from 'domain/exploration/OutcomeObjectFactory'; + export class AnswerClassificationResult { - // TODO(#7165): Replace 'any' with the exact type. This has been kept as - // 'any' because 'outcome' is an outcome domain object and this can be - // directly typed to 'Outcome' type once 'OutcomeObjectFactory' is upgraded. - outcome: any; + outcome: Outcome; answerGroupIndex: number; ruleIndex: number; classificationCategorization: string; constructor( - outcome: any, answerGroupIndex: number, ruleIndex: number, + outcome: Outcome, answerGroupIndex: number, ruleIndex: number, classificationCategorization: string) { this.outcome = outcome; this.answerGroupIndex = answerGroupIndex; @@ -43,11 +42,8 @@ export class AnswerClassificationResult { providedIn: 'root' }) export class AnswerClassificationResultObjectFactory { - // TODO(#7165): Replace 'any' with the exact type. This has been kept as - // 'any' because 'outcome' is an outcome domain object and this can be - // directly typed to 'Outcome' type once 'OutcomeObjectFactory' is upgraded. createNew( - outcome: any, answerGroupIndex: number, ruleIndex: number, + outcome: Outcome, answerGroupIndex: number, ruleIndex: number, classificationCategorization: string): AnswerClassificationResult { return new AnswerClassificationResult( outcome, answerGroupIndex, ruleIndex, classificationCategorization); diff --git a/core/templates/domain/classifier/AnswerClassificationResultObjectFactorySpec.ts b/core/templates/domain/classifier/AnswerClassificationResultObjectFactorySpec.ts index 66aaf3e1b30e..29a417c5d158 100755 --- a/core/templates/domain/classifier/AnswerClassificationResultObjectFactorySpec.ts +++ b/core/templates/domain/classifier/AnswerClassificationResultObjectFactorySpec.ts @@ -18,62 +18,20 @@ import { AnswerClassificationResultObjectFactory } from 'domain/classifier/AnswerClassificationResultObjectFactory'; - -require('domain/exploration/OutcomeObjectFactory.ts'); -require( - 'pages/exploration-player-page/services/answer-classification.service.ts'); - -class MockSubtitledHtml { - _html: string; - _contentId: string; - constructor(html: string, contentId: string) { - this._html = html; - this._contentId = contentId; - } -} - -class MockOutcome { - dest: string; - feedback: MockSubtitledHtml; - labelledAsCorrect: boolean; - paramChanges: any; - refresherExplorationId: any; - missingPrerequisiteSkillId: any; - constructor( - dest: string, feedback: MockSubtitledHtml, labelledAsCorrect: boolean, - paramChanges: any, refresherExplorationId: any, - missingPrerequisiteSkillId: any) { - this.dest = dest; - this.feedback = feedback; - this.labelledAsCorrect = labelledAsCorrect; - this.paramChanges = paramChanges; - this.refresherExplorationId = refresherExplorationId; - this.missingPrerequisiteSkillId = missingPrerequisiteSkillId; - } -} - -class MockOutcomeObjectFactory { - createNew( - dest: string, feedbackTextId: string, feedbackText: string, - paramChanges: any) { - return new MockOutcome( - dest, - new MockSubtitledHtml(feedbackText, feedbackTextId), - false, - paramChanges, - null, - null); - } -} +import { SubtitledHtmlObjectFactory } from + 'domain/exploration/SubtitledHtmlObjectFactory'; +import { OutcomeObjectFactory } from + 'domain/exploration/OutcomeObjectFactory'; describe('Answer classification result object factory', () => { let acrof: AnswerClassificationResultObjectFactory; - let oof: MockOutcomeObjectFactory; + let oof: OutcomeObjectFactory; let DEFAULT_OUTCOME_CLASSIFICATION: string; beforeEach(() => { acrof = new AnswerClassificationResultObjectFactory(); - oof = new MockOutcomeObjectFactory(); + oof = new OutcomeObjectFactory( + new SubtitledHtmlObjectFactory()); DEFAULT_OUTCOME_CLASSIFICATION = 'default_outcome'; }); diff --git a/core/templates/domain/exploration/ExplorationObjectFactory.ts b/core/templates/domain/exploration/ExplorationObjectFactory.ts index eab7975d37b0..0b93c91fed9e 100644 --- a/core/templates/domain/exploration/ExplorationObjectFactory.ts +++ b/core/templates/domain/exploration/ExplorationObjectFactory.ts @@ -24,29 +24,54 @@ import cloneDeep from 'lodash/cloneDeep'; import { AppConstants } from 'app.constants'; import { LoggerService } from 'services/contextual/logger.service'; +import { IParamChangeBackendDict, ParamChange } from + 'domain/exploration/ParamChangeObjectFactory'; import { ParamChangesObjectFactory } from 'domain/exploration/ParamChangesObjectFactory'; -import { ParamSpecsObjectFactory } from +import { IParamSpecsBackendDict, ParamSpecs, ParamSpecsObjectFactory } from 'domain/exploration/ParamSpecsObjectFactory'; -import { StatesObjectFactory } from 'domain/exploration/StatesObjectFactory'; +import { IEndExplorationCustomizationArgs, IInteractionCustomizationArgs } from + 'interactions/customization-args-defs'; +import { Interaction } from + 'domain/exploration/InteractionObjectFactory'; +import { IBindableVoiceovers } from + 'domain/exploration/RecordedVoiceoversObjectFactory'; +import { State } from 'domain/state/StateObjectFactory'; +import { + IStateObjectsBackendDict, + IVoiceoverObjectsDict, + States, + StatesObjectFactory +} from 'domain/exploration/StatesObjectFactory'; import { UrlInterpolationService } from 'domain/utilities/url-interpolation.service'; +import { Voiceover } from 'domain/exploration/VoiceoverObjectFactory'; const INTERACTION_SPECS = require('interactions/interaction_specs.json'); +interface IExplorationBackendDict { + 'init_state_name': string; + 'param_changes': IParamChangeBackendDict[]; + 'param_specs': IParamSpecsBackendDict; + 'states': IStateObjectsBackendDict; + 'title': string; + 'language_code': string; +} + export class Exploration { - initStateName; - paramChanges; - paramSpecs; - states; - title; - languageCode; + initStateName: string; + paramChanges: ParamChange[]; + paramSpecs: ParamSpecs; + states: States; + title: string; + languageCode: string; logger: LoggerService; urlInterpolationService: UrlInterpolationService; - // TODO(#7165): Replace any with exact type. + constructor( - initStateName: string, paramChanges: any, paramSpecs: any, states: any, - title: string, languageCode: string, loggerService: LoggerService, + initStateName: string, paramChanges: ParamChange[], + paramSpecs: ParamSpecs, states: States, title: string, + languageCode: string, loggerService: LoggerService, urlInterpolationService: UrlInterpolationService) { this.initStateName = initStateName; this.paramChanges = paramChanges; @@ -65,21 +90,21 @@ export class Exploration { INTERACTION_SPECS[this.getInteractionId(stateName)].is_terminal); } - // TODO(#7165): Replace any with exact type. - getAuthorRecommendedExpIds(stateName: string): any { + getAuthorRecommendedExpIds(stateName: string): string[] { if (!this.isStateTerminal(stateName)) { throw new Error( 'Tried to get recommendations for a non-terminal state: ' + stateName); } - const customizationArgs = this.getInteractionCustomizationArgs(stateName); + const customizationArgs = ( + this.getInteractionCustomizationArgs( + stateName)); return customizationArgs && customizationArgs.recommendedExplorationIds ? customizationArgs.recommendedExplorationIds.value : null; } - // TODO(#7165): Replace any with exact type. - getInteraction(stateName: string): any { + getInteraction(stateName: string): Interaction { let state = this.states.getState(stateName); if (!state) { this.logger.error('Invalid state name: ' + stateName); @@ -96,8 +121,8 @@ export class Exploration { return interaction.id; } - // TODO(#7165): Replace any with exact type. - getInteractionCustomizationArgs(stateName: string): any { + getInteractionCustomizationArgs( + stateName: string): IInteractionCustomizationArgs { let interaction = this.getInteraction(stateName); if (interaction === null) { return null; @@ -118,8 +143,7 @@ export class Exploration { ''); } - // TODO(#7165): Replace any with exact type. - getInteractionThumbnailSrc(stateName: string): any { + getInteractionThumbnailSrc(stateName: string): string { // TODO(sll): Unify this with the 'choose interaction' modal in // state_editor_interaction.html. let interactionId = this.getInteractionId(stateName); @@ -139,16 +163,15 @@ export class Exploration { INTERACTION_SPECS[interactionId].display_mode === AppConstants.INTERACTION_DISPLAY_MODE_INLINE); } - // TODO(#7165): Replace any with exact type. - getStates(): any { + getStates(): States { return cloneDeep(this.states); } - // TODO(#7165): Replace any with exact type. - getState(stateName: string): any { + + getState(stateName: string): State { return this.states.getState(stateName); } - // TODO(#7165): Replace any with exact type. - getInitialState(): any { + + getInitialState(): State { return this.getState(this.initStateName); } @@ -159,8 +182,8 @@ export class Exploration { getUninterpolatedContentHtml(stateName: string): string { return this.getState(stateName).content.getHtml(); } - // TODO(#7165): Replace any with exact type. - getVoiceovers(stateName: string): any { + + getVoiceovers(stateName: string): IBindableVoiceovers { let state = this.getState(stateName); if (!state) { this.logger.error('Invalid state name: ' + stateName); @@ -171,9 +194,9 @@ export class Exploration { return recordedVoiceovers.getBindableVoiceovers( contentId); } - // TODO(#7165): Replace any with exact type. + getVoiceover( - stateName: string, languageCode: string): any { + stateName: string, languageCode: string): Voiceover { let state = this.getState(stateName); if (!state) { this.logger.error('Invalid state name: ' + stateName); @@ -184,8 +207,8 @@ export class Exploration { const voiceovers = recordedVoiceovers.getVoiceover(contentId, languageCode); return voiceovers || null; } - // TODO(#7165): Replace any with exact type. - getAllVoiceovers(languageCode: string): any { + + getAllVoiceovers(languageCode: string): IVoiceoverObjectsDict { return this.states.getAllVoiceovers(languageCode); } @@ -193,7 +216,7 @@ export class Exploration { return this.languageCode; } - getAllVoiceoverLanguageCodes(): Array { + getAllVoiceoverLanguageCodes(): string[] { return this.states.getAllVoiceoverLanguageCodes(); } } @@ -208,9 +231,8 @@ export class ExplorationObjectFactory { private statesObjectFactory: StatesObjectFactory, private urlInterpolationService: UrlInterpolationService) {} - // TODO(#7165): Replace any with exact type. - createFromBackendDict(explorationBackendDict: any): Exploration { - /* eslint-enable dot-notation */ + createFromBackendDict( + explorationBackendDict: IExplorationBackendDict): Exploration { return new Exploration( explorationBackendDict.init_state_name, this.paramChangesObjectFactory.createFromBackendList( diff --git a/core/templates/domain/exploration/ParamSpecsObjectFactory.ts b/core/templates/domain/exploration/ParamSpecsObjectFactory.ts index 8e553d82f207..5bff229739f9 100644 --- a/core/templates/domain/exploration/ParamSpecsObjectFactory.ts +++ b/core/templates/domain/exploration/ParamSpecsObjectFactory.ts @@ -24,7 +24,7 @@ import { downgradeInjectable } from '@angular/upgrade/static'; import { IParamSpecBackendDict, ParamSpec, ParamSpecObjectFactory } from 'domain/exploration/ParamSpecObjectFactory'; -interface IParamSpecsBackendDict { +export interface IParamSpecsBackendDict { [paramName: string]: IParamSpecBackendDict; } diff --git a/core/templates/domain/exploration/StatesObjectFactory.ts b/core/templates/domain/exploration/StatesObjectFactory.ts index c76430d4e568..ce0c5239fb65 100644 --- a/core/templates/domain/exploration/StatesObjectFactory.ts +++ b/core/templates/domain/exploration/StatesObjectFactory.ts @@ -19,7 +19,12 @@ import { downgradeInjectable } from '@angular/upgrade/static'; import { Injectable } from '@angular/core'; -import { StateObjectFactory, State } from 'domain/state/StateObjectFactory'; +import { + IStateBackendDict, + StateObjectFactory, + State +} from 'domain/state/StateObjectFactory'; +import { Voiceover } from 'domain/exploration/VoiceoverObjectFactory'; const INTERACTION_SPECS = require('interactions/interaction_specs.json'); @@ -27,15 +32,20 @@ export interface IStateObjectsDict { [state: string]: State; } +export interface IStateObjectsBackendDict { + [state: string]: IStateBackendDict; +} + +export interface IVoiceoverObjectsDict { + [state: string]: Voiceover[]; +} + export class States { - _stateObject; - _states; - constructor(stateObject: StateObjectFactory, states: any) { - this._stateObject = stateObject; - this._states = states; - } + constructor( + private _stateObject: StateObjectFactory, + private _states: IStateObjectsDict) { } - getState(stateName: string): any { + getState(stateName: string): State { return this._states[stateName]; } @@ -43,14 +53,14 @@ export class States { // with an object to represent data to be manipulated inside // ExplorationDiffService. - getStateObjects(): any { + getStateObjects(): IStateObjectsDict { return this._states; } addState(newStateName: string): void { this._states[newStateName] = this._stateObject.createDefaultState( newStateName); } - setState(stateName: string, stateData: any): void { + setState(stateName: string, stateData: State): void { // We use the copy method defined in the StateObjectFactory to make // sure that this._states[stateName] remains a State object as opposed to // Object.assign(..) which returns an object with the content of stateData. @@ -96,10 +106,10 @@ export class States { } } } - getStateNames(): Array { + getStateNames(): string[] { return Object.keys(this._states); } - getFinalStateNames(): Array { + getFinalStateNames(): string[] { var finalStateNames = []; for (var stateName in this._states) { var interaction = this._states[stateName].interaction; @@ -110,7 +120,7 @@ export class States { return finalStateNames; } - getAllVoiceoverLanguageCodes(): Array { + getAllVoiceoverLanguageCodes(): string[] { var allAudioLanguageCodes = []; for (var stateName in this._states) { var state = this._states[stateName]; @@ -128,7 +138,7 @@ export class States { return allAudioLanguageCodes; } - getAllVoiceovers(languageCode: string): any { + getAllVoiceovers(languageCode: string): IVoiceoverObjectsDict { var allAudioTranslations = {}; for (var stateName in this._states) { var state = this._states[stateName]; @@ -152,10 +162,7 @@ export class States { }) export class StatesObjectFactory { constructor(private stateObject: StateObjectFactory) {} - // TODO(ankita240796): Remove the bracket notation once Angular2 gets in. - /* eslint-disable dot-notation */ - createFromBackendDict(statesBackendDict: any): States { - /* eslint-enable dot-notation */ + createFromBackendDict(statesBackendDict: IStateObjectsBackendDict): States { var stateObjectsDict = {}; for (var stateName in statesBackendDict) { stateObjectsDict[stateName] = this.stateObject.createFromBackendDict( diff --git a/core/templates/domain/feedback_thread/FeedbackThreadObjectFactory.ts b/core/templates/domain/feedback_thread/FeedbackThreadObjectFactory.ts index b440fd5ef119..c901cac12c75 100644 --- a/core/templates/domain/feedback_thread/FeedbackThreadObjectFactory.ts +++ b/core/templates/domain/feedback_thread/FeedbackThreadObjectFactory.ts @@ -25,7 +25,7 @@ import { ThreadMessage } from import { ThreadMessageSummary, ThreadMessageSummaryObjectFactory } from 'domain/feedback_message/ThreadMessageSummaryObjectFactory'; -interface IFeedbackThreadBackendDict { +export interface IFeedbackThreadBackendDict { 'status': string; 'subject': string; 'summary': string; diff --git a/core/templates/domain/state/StateObjectFactory.ts b/core/templates/domain/state/StateObjectFactory.ts index e47c17c23345..a41252ad25a0 100644 --- a/core/templates/domain/state/StateObjectFactory.ts +++ b/core/templates/domain/state/StateObjectFactory.ts @@ -43,7 +43,7 @@ import { const constants = require('constants.ts'); -interface IStateBackendDict { +export interface IStateBackendDict { 'classifier_model_id': string; 'content': ISubtitledHtmlBackendDict; 'interaction': IInteractionBackendDict; diff --git a/core/templates/domain/statistics/LearnerAnswerDetailsObjectFactory.ts b/core/templates/domain/statistics/LearnerAnswerDetailsObjectFactory.ts index a41673775ec8..79a8631c69f9 100644 --- a/core/templates/domain/statistics/LearnerAnswerDetailsObjectFactory.ts +++ b/core/templates/domain/statistics/LearnerAnswerDetailsObjectFactory.ts @@ -22,17 +22,19 @@ import { downgradeInjectable } from '@angular/upgrade/static'; import { LearnerAnswerInfo } from 'domain/statistics/LearnerAnswerInfoObjectFactory'; +import { IInteractionCustomizationArgs } from + 'interactions/customization-args-defs'; export class LearnerAnswerDetails { expId: string; stateName: string; interactionId: string; - customizationArgs: any; + customizationArgs: IInteractionCustomizationArgs; learnerAnswerInfoData: LearnerAnswerInfo[]; constructor( expId: string, stateName: string, interactionId: string, - customizationArgs: any, + customizationArgs: IInteractionCustomizationArgs, learnerAnswerInfoData: LearnerAnswerInfo[]) { this.expId = expId; this.stateName = stateName; @@ -66,7 +68,7 @@ export class LearnerAnswerDetails { export class LearnerAnswerDetailsObjectFactory { createDefaultLearnerAnswerDetails( expId: string, stateName: string, interactionId: string, - customizationArgs: any, + customizationArgs: IInteractionCustomizationArgs, learnerAnswerInfoData: LearnerAnswerInfo[]): LearnerAnswerDetails { return new LearnerAnswerDetails( expId, stateName, interactionId, customizationArgs, diff --git a/core/templates/domain/suggestion/SuggestionObjectFactory.ts b/core/templates/domain/suggestion/SuggestionObjectFactory.ts index 949d9c108e6b..da23f4d5177a 100644 --- a/core/templates/domain/suggestion/SuggestionObjectFactory.ts +++ b/core/templates/domain/suggestion/SuggestionObjectFactory.ts @@ -32,7 +32,7 @@ interface ISuggestionChangeBackendDict { 'old_value': ISuggestionChangeValue; } -interface ISuggestionBackendDict { +export interface ISuggestionBackendDict { 'suggestion_type': string; 'suggestion_id': string; 'target_type': string; diff --git a/core/templates/pages/exploration-editor-page/statistics-tab/services/state-improvement-suggestion.service.spec.ts b/core/templates/pages/exploration-editor-page/statistics-tab/services/state-improvement-suggestion.service.spec.ts index e588ce7ccf44..7b00c9eb2818 100644 --- a/core/templates/pages/exploration-editor-page/statistics-tab/services/state-improvement-suggestion.service.spec.ts +++ b/core/templates/pages/exploration-editor-page/statistics-tab/services/state-improvement-suggestion.service.spec.ts @@ -36,6 +36,7 @@ describe('StateImprovementSuggestionService', () => { // A self-looping state. var statesDict1 = { state: { + classifier_model_id: null, content: { content_id: 'content', html: 'content' @@ -49,6 +50,8 @@ describe('StateImprovementSuggestionService', () => { }, interaction: { id: 'RuleTest', + confirmed_unclassified_answers: null, + customization_args: {}, answer_groups: [{ outcome: { dest: 'unused', @@ -58,7 +61,8 @@ describe('StateImprovementSuggestionService', () => { }, labelled_as_correct: false, param_changes: [], - refresher_exploration_id: null + refresher_exploration_id: null, + missing_prerequisite_skill_id: null }, rule_specs: [{ inputs: { @@ -66,6 +70,8 @@ describe('StateImprovementSuggestionService', () => { }, rule_type: 'Equals' }], + training_data: ['training_data'], + tagged_skill_misconception_id: 'skill_id-1' }], default_outcome: { dest: 'state', @@ -73,9 +79,20 @@ describe('StateImprovementSuggestionService', () => { content_id: 'default_outcome', html: '' }, - param_changes: [] + labelled_as_correct: false, + param_changes: [], + refresher_exploration_id: null, + missing_prerequisite_skill_id: null }, - hints: [] + hints: [], + solution: { + answer_is_exclusive: false, + correct_answer: 'This is a correct answer!', + explanation: { + content_id: 'solution', + html: 'This is the explanation to the answer' + } + } }, param_changes: [], solicit_answer_details: false, @@ -92,6 +109,7 @@ describe('StateImprovementSuggestionService', () => { // A non-looping state. var statesDict2 = { initial: { + classifier_model_id: null, content: { content_id: 'content', html: 'content' @@ -105,6 +123,8 @@ describe('StateImprovementSuggestionService', () => { }, interaction: { id: 'RuleTest', + confirmed_unclassified_answers: null, + customization_args: {}, answer_groups: [{ outcome: { dest: 'unused', @@ -114,14 +134,17 @@ describe('StateImprovementSuggestionService', () => { }, labelled_as_correct: false, param_changes: [], - refresher_exploration_id: null + refresher_exploration_id: null, + missing_prerequisite_skill_id: null }, rule_specs: [{ inputs: { x: 10 }, rule_type: 'Equals' - }] + }], + training_data: ['training_data'], + tagged_skill_misconception_id: 'skill_id-1' }], default_outcome: { dest: 'end', @@ -129,9 +152,20 @@ describe('StateImprovementSuggestionService', () => { content_id: 'default_outcome', html: '' }, - param_changes: [] + labelled_as_correct: false, + param_changes: [], + refresher_exploration_id: null, + missing_prerequisite_skill_id: null }, - hints: [] + hints: [], + solution: { + answer_is_exclusive: false, + correct_answer: 'This is a correct answer!', + explanation: { + content_id: 'solution', + html: 'This is the explanation to the answer' + } + } }, param_changes: [], solicit_answer_details: false, @@ -144,6 +178,7 @@ describe('StateImprovementSuggestionService', () => { }, }, end: { + classifier_model_id: null, content: { content_id: 'content', html: 'content' @@ -157,6 +192,8 @@ describe('StateImprovementSuggestionService', () => { }, interaction: { id: 'RuleTest', + confirmed_unclassified_answers: null, + customization_args: {}, answer_groups: [{ outcome: { dest: 'unused', @@ -166,14 +203,17 @@ describe('StateImprovementSuggestionService', () => { }, labelled_as_correct: false, param_changes: [], - refresher_exploration_id: null + refresher_exploration_id: null, + missing_prerequisite_skill_id: null }, rule_specs: [{ inputs: { x: 10 }, rule_type: 'Equals' - }] + }], + training_data: ['training_data'], + tagged_skill_misconception_id: 'skill_id-1' }], default_outcome: { dest: null, @@ -181,9 +221,20 @@ describe('StateImprovementSuggestionService', () => { content_id: 'default_outcome', html: '' }, - param_changes: [] + labelled_as_correct: false, + param_changes: [], + refresher_exploration_id: null, + missing_prerequisite_skill_id: null }, - hints: [] + hints: [], + solution: { + answer_is_exclusive: false, + correct_answer: 'This is a correct answer!', + explanation: { + content_id: 'solution', + html: 'This is the explanation to the answer' + } + } }, param_changes: [], solicit_answer_details: false, diff --git a/core/templates/services/suggestions.service.ts b/core/templates/services/suggestions.service.ts index aa9777169b6d..089df734d76b 100644 --- a/core/templates/services/suggestions.service.ts +++ b/core/templates/services/suggestions.service.ts @@ -19,10 +19,13 @@ import { downgradeInjectable } from '@angular/upgrade/static'; import { Injectable } from '@angular/core'; +import { ISuggestionBackendDict } from + 'domain/suggestion/SuggestionObjectFactory'; + @Injectable({providedIn: 'root'}) export class SuggestionsService { - // TODO(#7165): Replace 'any' with the exact type. - getThreadIdFromSuggestionBackendDict(suggestionBackendDict: any): string { + getThreadIdFromSuggestionBackendDict( + suggestionBackendDict: ISuggestionBackendDict): string { return suggestionBackendDict.suggestion_id; } } diff --git a/scripts/linters/excluded_any_type_files.json b/scripts/linters/excluded_any_type_files.json index c60e577898b3..2626d362fd26 100644 --- a/scripts/linters/excluded_any_type_files.json +++ b/scripts/linters/excluded_any_type_files.json @@ -2,19 +2,13 @@ "core/templates/combined-tests.spec.ts", "core/templates/components/entity-creation-services/collection-creation-backend-api.service.ts", "core/templates/components/entity-creation-services/question-creation.service.ts", - "core/templates/components/state-editor/state-editor-properties-services/state-hints.service.ts", - "core/templates/components/state-editor/state-editor-properties-services/state-property.service.ts", - "core/templates/domain/classifier/AnswerClassificationResultObjectFactory.ts", - "core/templates/domain/classifier/AnswerClassificationResultObjectFactorySpec.ts", "core/templates/domain/collection/collection-rights-backend-api.service.ts", "core/templates/domain/collection/editable-collection-backend-api.service.ts", "core/templates/domain/collection/read-only-collection-backend-api.service.ts", "core/templates/domain/collection/search-explorations-backend-api.service.ts", "core/templates/domain/exploration/ExplorationMetadataObjectFactory.ts", - "core/templates/domain/exploration/ExplorationObjectFactory.ts", "core/templates/domain/exploration/InteractionObjectFactory.ts", "core/templates/domain/exploration/SolutionObjectFactory.ts", - "core/templates/domain/exploration/StatesObjectFactory.ts", "core/templates/domain/objects/NumberWithUnitsObjectFactory.ts", "core/templates/domain/objects/UnitsObjectFactory.ts", "core/templates/domain/opportunity/ExplorationOpportunitySummaryObjectFactory.ts", @@ -30,7 +24,6 @@ "core/templates/domain/skill/MisconceptionObjectFactorySpec.ts", "core/templates/domain/skill/skill-creation-backend-api.service.ts", "core/templates/domain/skill/skill-mastery-backend-api.service.ts", - "core/templates/domain/statistics/LearnerAnswerDetailsObjectFactory.ts", "core/templates/domain/statistics/PlaythroughObjectFactory.ts", "core/templates/domain/story_viewer/story-viewer-backend-api.service.ts", "core/templates/domain/subtopic_viewer/subtopic-viewer-backend-api.service.ts", @@ -51,7 +44,6 @@ "core/templates/services/schema-default-value.service.ts", "core/templates/services/schema-undefined-last-element.service.ts", "core/templates/services/suggestion-modal.service.ts", - "core/templates/services/suggestions.service.ts", "extensions/interactions/CodeRepl/code-repl-prediction.service.ts", "extensions/interactions/CodeRepl/directives/code-repl-validation.service.spec.ts", "extensions/interactions/Continue/directives/continue-validation.service.spec.ts", From 9fd45ce119ce3a0a169b839cd067a6bab64ef93a Mon Sep 17 00:00:00 2001 From: Nishant Mittal Date: Thu, 2 Jul 2020 04:58:53 +0530 Subject: [PATCH 2/2] Fix FE tests --- .../state-hints.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.spec.ts b/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.spec.ts index 7459143e7419..44c42c117185 100644 --- a/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.spec.ts +++ b/core/templates/components/state-editor/state-editor-properties-services/state-hints.service.spec.ts @@ -47,7 +47,7 @@ describe('State hints service', () => { html: '

math

', content_id: 'hint_1' } - }].map(hof.createFromBackendDict); + }].map(item => hof.createFromBackendDict(item)); shs.init(StateName, value); expect(shs.setActiveHintIndex).toHaveBeenCalled(); });