Repository: oppia/oppia

Issue:
Eliminate 'any' type in favor of its exact type.
<!--
  - Thanks for taking the time to propose a new feature for the Oppia project.
  - Before filing a new issue, please do a quick search to check that it hasn't
  - already been filed on the [issue tracker](https://github.com/oppia/oppia/issues)._
  -->
NOTE - @nishantwrp will be working on this as a part of his GSoC project.

Eliminate the use of `any` type used in the TS files. They must be replaced with an explicit type that would bring the codebase to a strongly typed state.

- [ ] core/templates/dev/head/services/SchemaDefaultValueService.ts
- [ ] core/templates/dev/head/services/SchemaUndefinedLastElementService.ts
- [ ] extensions/interactions/ImageClickInput/directives/ImageClickInputRulesService.ts
- [ ] core/templates/dev/head/domain/statistics/ImprovementActionButtonObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/ParamTypeObjectFactory.ts
- [ ] extensions/interactions/MathExpressionInput/directives/MathExpressionInputRulesService.ts
- [ ] extensions/interactions/rulesSpec.ts
- [ ] core/templates/dev/head/domain/statistics/ImprovementActionButtonObjectFactory.ts
- [ ] core/templates/dev/head/pages/exploration-player-page/services/learner-params.service.ts
- [ ] extensions/interactions/GraphInput/directives/GraphDetailService.ts
- [ ] extensions/interactions/GraphInput/directives/GraphUtilsService.ts
- [ ] core/templates/dev/head/domain/classifier/AnswerClassificationResultObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/RuleObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/ExplorationDraftObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/RecordedVoiceoversObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/ParamSpecsObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/WrittenTranslationsObjectFactory.ts
- [ ] extensions/interactions/baseInteractionValidationService.ts
- [ ] core/templates/dev/head/domain/statistics/LearnerActionObjectFactory.ts
- [ ] core/templates/dev/head/domain/objects/UnitsObjectFactory.ts
- [ ] core/templates/dev/head/domain/collection/CollectionNodeObjectFactory.ts
- [ ] core/templates/dev/head/components/graph-services/graph-layout.service.ts
- [ ] core/templates/dev/head/domain/exploration/AnswerGroupObjectFactory.ts
- [ ] extensions/interactions/ImageClickInput/directives/ImageClickInputValidationServiceSpec.ts
- [ ] extensions/interactions/MultipleChoiceInput/directives/MultipleChoiceInputValidationServiceSpec.ts
- [ ] core/templates/dev/head/domain/story/StoryContentsObjectFactory.ts
- [ ] core/templates/dev/head/domain/story/StoryObjectFactory.ts
- [ ] core/templates/dev/head/services/SpeechSynthesisChunkerService.ts
- [ ] core/templates/dev/head/components/state-editor/state-editor-properties-services/state-editor.service.ts
- [ ] core/templates/dev/head/components/state-editor/state-editor-properties-services/state-property.service.ts
- [ ] core/templates/dev/head/domain/collection/CollectionValidationService.ts
- [ ] core/templates/dev/head/services/AutogeneratedAudioPlayerService.ts
- [ ] core/templates/dev/head/domain/topic/TopicObjectFactory.ts
Eliminate 'any' type in favor of its exact type.
<!--
  - Thanks for taking the time to propose a new feature for the Oppia project.
  - Before filing a new issue, please do a quick search to check that it hasn't
  - already been filed on the [issue tracker](https://github.com/oppia/oppia/issues)._
  -->
NOTE - @nishantwrp will be working on this as a part of his GSoC project.

Eliminate the use of `any` type used in the TS files. They must be replaced with an explicit type that would bring the codebase to a strongly typed state.

- [ ] core/templates/dev/head/services/SchemaDefaultValueService.ts
- [ ] core/templates/dev/head/services/SchemaUndefinedLastElementService.ts
- [ ] extensions/interactions/ImageClickInput/directives/ImageClickInputRulesService.ts
- [ ] core/templates/dev/head/domain/statistics/ImprovementActionButtonObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/ParamTypeObjectFactory.ts
- [ ] extensions/interactions/MathExpressionInput/directives/MathExpressionInputRulesService.ts
- [ ] extensions/interactions/rulesSpec.ts
- [ ] core/templates/dev/head/domain/statistics/ImprovementActionButtonObjectFactory.ts
- [ ] core/templates/dev/head/pages/exploration-player-page/services/learner-params.service.ts
- [ ] extensions/interactions/GraphInput/directives/GraphDetailService.ts
- [ ] extensions/interactions/GraphInput/directives/GraphUtilsService.ts
- [ ] core/templates/dev/head/domain/classifier/AnswerClassificationResultObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/RuleObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/ExplorationDraftObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/RecordedVoiceoversObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/ParamSpecsObjectFactory.ts
- [ ] core/templates/dev/head/domain/exploration/WrittenTranslationsObjectFactory.ts
- [ ] extensions/interactions/baseInteractionValidationService.ts
- [ ] core/templates/dev/head/domain/statistics/LearnerActionObjectFactory.ts
- [ ] core/templates/dev/head/domain/objects/UnitsObjectFactory.ts
- [ ] core/templates/dev/head/domain/collection/CollectionNodeObjectFactory.ts
- [ ] core/templates/dev/head/components/graph-services/graph-layout.service.ts
- [ ] core/templates/dev/head/domain/exploration/AnswerGroupObjectFactory.ts
- [ ] extensions/interactions/ImageClickInput/directives/ImageClickInputValidationServiceSpec.ts
- [ ] extensions/interactions/MultipleChoiceInput/directives/MultipleChoiceInputValidationServiceSpec.ts
- [ ] core/templates/dev/head/domain/story/StoryContentsObjectFactory.ts
- [ ] core/templates/dev/head/domain/story/StoryObjectFactory.ts
- [ ] core/templates/dev/head/services/SpeechSynthesisChunkerService.ts
- [ ] core/templates/dev/head/components/state-editor/state-editor-properties-services/state-editor.service.ts
- [ ] core/templates/dev/head/components/state-editor/state-editor-properties-services/state-property.service.ts
- [ ] core/templates/dev/head/domain/collection/CollectionValidationService.ts
- [ ] core/templates/dev/head/services/AutogeneratedAudioPlayerService.ts
- [ ] core/templates/dev/head/domain/topic/TopicObjectFactory.ts


Discussion:
@kaylahardie Please don't use fixes when you are not solving the entire issue. Use fixes part of instead.
Sounds good @nishantwrp! Thanks so much for the feedback :)
@kaylahardie Please don't use fixes when you are not solving the entire issue. Use fixes part of instead.
Sounds good @nishantwrp! Thanks so much for the feedback :)

Resolving patch:
diff --git a/scripts/linters/js_ts_linter.py b/scripts/linters/js_ts_linter.py
--- a/scripts/linters/js_ts_linter.py
+++ b/scripts/linters/js_ts_linter.py
@@ -20,7 +20,6 @@
 from __future__ import unicode_literals  # pylint: disable=import-only-modules
 
 import collections
-import json
 import os
 import re
 import shutil
@@ -48,12 +47,6 @@
 # pylint: enable=wrong-import-order
 # pylint: enable=wrong-import-position
 
-FILES_EXCLUDED_FROM_ANY_TYPE_CHECK_PATH = os.path.join(
-    CURR_DIR, 'scripts', 'linters', 'excluded_any_type_files.json')
-
-FILES_EXCLUDED_FROM_ANY_TYPE_CHECK = json.load(python_utils.open_file(
-    FILES_EXCLUDED_FROM_ANY_TYPE_CHECK_PATH, 'r'))
-
 COMPILED_TYPESCRIPT_TMP_PATH = 'tmpcompiledjs/'
 
 
@@ -239,72 +232,6 @@ def _get_compiled_ts_filepath(self, filepath):
             os.path.relpath(filepath).replace('.ts', '.js'))
         return compiled_js_filepath
 
-    def _check_any_type(self):
-        """Checks if the type of any variable is declared as 'any'
-        in TypeScript files.
-        """
-        summary_messages = []
-        if self.verbose_mode_enabled:
-            python_utils.PRINT('Starting any type check')
-            python_utils.PRINT('----------------------------------------')
-
-        # This pattern is used to match cases like ': any'.
-        any_type_pattern = r':\ *any'
-
-        # This pattern is used to match cases where the previous line ended
-        # with a ':', so we know this line begins with a type.
-        starts_with_any_pattern = r'^\ *any'
-
-        with linter_utils.redirect_stdout(sys.stdout):
-            failed = False
-
-            for file_path in self.all_filepaths:
-                if file_path in FILES_EXCLUDED_FROM_ANY_TYPE_CHECK:
-                    continue
-
-                file_content = self.file_cache.read(file_path)
-                starts_with_type = False
-
-                for line_number, line in enumerate(file_content.split('\n')):
-                    if starts_with_type and re.findall(
-                            starts_with_any_pattern, line):
-                        failed = True
-                        summary_message = (
-                            '%s --> \'any\' type found at line %s. Please do '
-                            'not declare variable as \'any\' type' % (
-                                file_path, line_number + 1))
-                        python_utils.PRINT(summary_message)
-                        summary_messages.append(summary_message)
-                        python_utils.PRINT('')
-
-                    if re.findall(any_type_pattern, line):
-                        failed = True
-                        summary_message = (
-                            '%s --> \'any\' type found at line %s. Please do '
-                            'not declare variable as \'any\' type' % (
-                                file_path, line_number + 1))
-                        python_utils.PRINT(summary_message)
-                        summary_messages.append(summary_message)
-                        python_utils.PRINT('')
-
-                    if line:
-                        starts_with_type = line[len(line) - 1] == ':'
-
-            if failed:
-                summary_message = (
-                    '%s \'any\' type check failed' % (
-                        linter_utils.FAILED_MESSAGE_PREFIX))
-            else:
-                summary_message = (
-                    '%s \'any\' type check passed' % (
-                        linter_utils.SUCCESS_MESSAGE_PREFIX))
-
-            python_utils.PRINT(summary_message)
-            summary_messages.append(summary_message)
-            python_utils.PRINT('')
-
-        return summary_messages
-
     def _check_http_requests(self):
         """Checks if the http requests are made only by
         backend-api.service.ts.
@@ -1071,7 +998,6 @@ def perform_all_lint_checks(self):
         self.parsed_expressions_in_files = (
             self._get_expressions_from_parsed_script())
 
-        any_type_messages = self._check_any_type()
         extra_js_files_messages = self._check_extra_js_files()
         http_requests_messages = self._check_http_requests()
         js_and_ts_component_messages = (
@@ -1087,7 +1013,7 @@ def perform_all_lint_checks(self):
         shutil.rmtree(COMPILED_TYPESCRIPT_TMP_PATH, ignore_errors=True)
 
         all_messages = (
-            any_type_messages + extra_js_files_messages +
+            extra_js_files_messages +
             http_requests_messages + js_and_ts_component_messages +
             directive_scope_messages + sorted_dependencies_messages +
             controller_dependency_messages + constant_declaration_messages +


Test patch:
diff --git a/scripts/linters/js_ts_linter_test.py b/scripts/linters/js_ts_linter_test.py
--- a/scripts/linters/js_ts_linter_test.py
+++ b/scripts/linters/js_ts_linter_test.py
@@ -60,8 +60,6 @@
     LINTER_TESTS_DIR, 'valid_constant_outside_class.constants.ajs.ts')
 VALID_BACKEND_API_SERVICE_FILEPATH = os.path.join(
     LINTER_TESTS_DIR, 'valid-backend-api.service.ts')
-INVALID_ANY_TYPE_FILEPATH = os.path.join(
-    LINTER_TESTS_DIR, 'invalid_any_type.ts')
 EXTRA_JS_FILEPATH = os.path.join('core', 'templates', 'demo.js')
 INVALID_COMPONENT_FILEPATH = os.path.join(
     LINTER_TESTS_DIR, 'invalid_two_component.ts')
@@ -115,37 +113,6 @@ def mock_parse_script(unused_file_content):
                 [], [VALID_JS_FILEPATH], FILE_CACHE,
                 True).perform_all_lint_checks()
 
-    def test_invalid_use_of_any_type(self):
-        def mock_compile_all_ts_files():
-            cmd = (
-                './node_modules/typescript/bin/tsc -outDir %s -allowJS %s '
-                '-lib %s -noImplicitUseStrict %s -skipLibCheck '
-                '%s -target %s -typeRoots %s %s typings/*') % (
-                    js_ts_linter.COMPILED_TYPESCRIPT_TMP_PATH +
-                    'scripts/linters/test_files/', 'true', 'es2017,dom', 'true',
-                    'true', 'es5', './node_modules/@types',
-                    INVALID_ANY_TYPE_FILEPATH)
-            subprocess.call(cmd, shell=True, stdout=subprocess.PIPE)
-
-        compile_all_ts_files_swap = self.swap(
-            js_ts_linter, 'compile_all_ts_files', mock_compile_all_ts_files)
-        excluded_files_swap = self.swap(
-            js_ts_linter, 'FILES_EXCLUDED_FROM_ANY_TYPE_CHECK',
-            [VALID_TS_FILEPATH])
-
-        with self.print_swap, excluded_files_swap, compile_all_ts_files_swap:
-            js_ts_linter.JsTsLintChecksManager(
-                [], [INVALID_ANY_TYPE_FILEPATH, VALID_TS_FILEPATH], FILE_CACHE,
-                True).perform_all_lint_checks()
-        shutil.rmtree(
-            js_ts_linter.COMPILED_TYPESCRIPT_TMP_PATH, ignore_errors=True)
-        self.assert_same_list_elements([
-            '\'any\' type found at line 20. Please do not declare variable'
-            ' as \'any\' type'], self.linter_stdout)
-        self.assert_same_list_elements([
-            '\'any\' type found at line 22. Please do not declare variable'
-            ' as \'any\' type'], self.linter_stdout)
-
     def test_check_extra_js_file_found(self):
         def mock_readlines(unused_self, unused_filepath):
             return ('var a = 10;\n',)
diff --git a/scripts/linters/test_files/invalid_any_type.ts b/scripts/linters/test_files/invalid_any_type.ts
deleted file mode 100644
--- a/scripts/linters/test_files/invalid_any_type.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2020 The Oppia Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Invalid syntax .ts file, used by scripts/linters/
- * js_ts_linter_test.py. This file use any type which is not allowed.
- */
-
-declare const require: any; // Use of any type is not allowed.
-declare const require:
-  any;