javascript-to-typescript

Migrate JavaScript to TypeScript

Example

constants:
  types_index_file_path: 'index.d.ts'
  tsconfig_contents: |
    {
      "compilerOptions": {
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve",
        "baseUrl": ".",
        "incremental": true,
        "strictNullChecks": true,
        "noImplicitAny": true,
        "noImplicitThis": true,
        "paths": {
          "~/*": ["./*"]
        }
      },
      "include": [
        "next-env.d.ts",
        "**/*.ts",
        "**/*.tsx",
        "./dist/types/**/*.ts"
      ],
      "exclude": ["node_modules"]
    }

setup:
  - name: run_terminal_command
    arguments:
      command: npm install

steps:
  # Create tsconfig.json
  - name: Create tsconfig.json
    tools:
      - name: create_file
        arguments:
          path_to_file: 'tsconfig.json'
          file_contents: '{{ tsconfig_contents }}'

  # extract types from .js files
  - name: Extract types from .js and jsx files
    tools:
      - name: async_each
        items: ['js', 'jsx']
        each_item:
          item_name: file_extension
          tools:
            - name: find_files_by_name_with_regex
              arguments:
                find_file_name_pattern: '\.{{ file_extension }}$'
              returns: files
            - name: async_each
              items: '{{ files }}'
              each_item:
                item_name: file
                tools:
                  - name: get_file_name
                    arguments:
                      path_to_file: '{{ file }}'
                      include_extension: false
                    returns: file_name
                  - name: make_variable
                    arguments:
                      value: '{{ file_name }}-{{ file_extension }}'
                    returns: file_name_with_extension
                  - name: get_content_from_file
                    arguments:
                      path_to_file: '{{ file }}'
                    returns: file_contents
                  - name: get_directory_from_file_path
                    arguments:
                      path_to_file: '{{ file }}'
                    returns: directory
                  - name: make_variable
                    arguments:
                      value: '{{ directory }}/{{ file_name_with_extension }}.types.d.ts'
                    returns: types_file_path
                  - name: edit_file
                    arguments:
                      path_to_file: '{{ types_file_path }}'
                      edit_prompt: |
                        Look closely at this Javascript file to find situations where custom types and enums should be defined when this file is converted to TypeScript. BE METICULOUS and create types for all objects, return values, parameters, and enums.
                        **Contents of {{ file }}:**
                        ```
                        {{ file_contents }}
                        ```

                        Write to this new {{ types_file_path }} file where the types and enums should be defined. Try to keep your output as DRY as possible. Add a comment at the top of the file that looks like `// Derived from {{ file }}`.

                        Do not define types for external libraries. They should have their own.

                        Export all types declared in this file.

  - name: Combine types from .d.ts files
    tools:
      - name: find_files_by_name_with_regex
        arguments:
          find_file_name_pattern: '\.(types\.d\.ts)$'
        returns: type_files
      - name: create_file_with_ai
        arguments:
          path_to_file: '{{ types_index_file_path }}'
          create_content_prompt: |
            ## Type declaration file paths
            ```
            {{ type_files }}
            ```
            ## Instructions
            Create an index file that re-exports all types from the above .types.d.ts files. Each export should be relative to the file's location.
            Example:
            Given the following .types.d.ts files:
            ```
            components/Button.types.d.ts
            utils/helpers.types.d.ts
            ```
            The index file should look like this:
            ```
            export * from '~/components/Button.types';
            export * from '~/utils/helpers.types';
            ```
        returns: global_types

  - name: Process .js and .jsx files
    tools:
      - name: async_each
        items: ['js', 'jsx']
        each_item:
          item_name: file_extension
          tools:
            - name: find_files_by_name_with_regex
              arguments:
                find_file_name_pattern: '\.{{ file_extension }}$'
              returns: files
            - name: async_each
              items: '{{ files }}'
              each_item:
                item_name: file
                tools:
                  - name: get_file_name
                    arguments:
                      path_to_file: '{{ file }}'
                      include_extension: false
                    returns: file_name
                  - name: make_variable
                    arguments:
                      value: '{{ file_name }}-{{ file_extension }}'
                    returns: file_name_with_extension
                  - name: get_content_from_file
                    arguments:
                      path_to_file: '{{ file }}'
                    returns: file_contents
                  - name: get_directory_from_file_path
                    arguments:
                      path_to_file: '{{ file }}'
                    returns: directory
                  - name: make_variable
                    arguments:
                      value: '{{ directory }}/{{ file_name_with_extension }}.types.d.ts'
                    returns: types_file_path
                  - name: edit_file
                    arguments:
                      path_to_file: '{{ file }}'
                      edit_prompt: |
                        ## Type declaration file ({{ types_file_path }})
                        ```
                        {{ type_file }}
                        ```
                        You can use `~` to refer to the root directory of the project.

                        ## Instructions
                        - Convert this JavaScript file to TypeScript. Use typing liberally and use the predefined custom types from {{ types_file_path }} when applicable (accessible via "./{{ file_name_with_extension }}.types"). NEVER try to import types from {{ types_file_path }} if they are not defined in the file.
                        - If importing code from another js or jsx file, assume that it has been converted to TypeScript.
                          Imported js file: `import { ... } from './example.js'`
                          After conversion: `import { ... } from './example'`
                        - When importing types, make sure to use the "type" keyword:
                          Correct type import: `import type { ... } from '...'`
                          Incorrect type import: `import { ... } from '...'`
                        - The tsconfig file looks like the following. You can use this to help you with the conversion rules and determining file paths:
                          ```
                          {{ tsconfig_contents }}
                          ```

  - name: Convert file extensions for js files
    tools:
      - name: find_files_by_name_with_regex
        arguments:
          find_file_name_pattern: '\.js$'
        returns: js_files
      - name: async_each
        items: '{{ js_files }}'
        each_item:
          item_name: file
          tools:
            - name: change_file_extension
              arguments:
                path_to_file: '{{ file }}'
                new_extension: '.ts'

  - name: Convert file extensions for jsx files
    tools:
      - name: find_files_by_name_with_regex
        arguments:
          find_file_name_pattern: '\.jsx$'
        returns: jsx_files
      - name: async_each
        items: '{{ jsx_files }}'
        each_item:
          item_name: file
          tools:
            - name: change_file_extension
              arguments:
                path_to_file: '{{ file }}'
                new_extension: '.tsx'

  - name: Update package.json
    tools:
      - name: find_files_by_name_with_regex
        arguments:
          find_file_name_pattern: 'package.json'
        returns: files
      - name: get_first
        arguments:
          array: '{{ files }}'
        returns: packagejson
      - name: get_directory_from_file_path
        arguments:
          path_to_file: '{{ packagejson }}'
        returns: packagejson_directory
      - name: edit_json
        arguments:
          path_to_file: '{{ packagejson }}'
          json_path: 'scripts'
          action: 'add'
          values:
            - key: 'build'
              value: 'tsc'
            - key: 'start'
              value: 'tsc && node dist/index.js'
      - name: run_terminal_command
        arguments:
          command: npm install --save-dev typescript @types/node
          path_to_directory: '{{ packagejson_directory }}'

  - name: Validate TypeScript Project
    tools:
      - name: validate_typescript_project
        arguments:
          max_context_depth: 3
          directory: '{{ react_directory }}'

Last updated