Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function overloads are showing up in StatementedNode.statements #1524

Open
ajvincent opened this issue Mar 19, 2024 · 3 comments
Open

Function overloads are showing up in StatementedNode.statements #1524

ajvincent opened this issue Mar 19, 2024 · 3 comments

Comments

@ajvincent
Copy link
Contributor

Describe the bug

Version: 22.0.0

To Reproduce

import {
  ModuleKind,
  ModuleResolutionKind,
  Project,
  type ProjectOptions,
  ScriptTarget,
} from "ts-morph";

const TSC_CONFIG: ProjectOptions = {
  "compilerOptions": {
    "lib": ["es2022"],
    "module": ModuleKind.ESNext,
    "target": ScriptTarget.ESNext,
    "moduleResolution": ModuleResolutionKind.NodeNext,
    "sourceMap": true,
    "declaration": true,
  },
  skipAddingFilesFromTsConfig: true,
  skipFileDependencyResolution: true,
  useInMemoryFileSystem: true,
};

const project = new Project(TSC_CONFIG);
const sourceFile = project.createSourceFile("foo.ts", `
function foo(x: number, y: string): void
function foo(x: number): void
{
  void(x);
}
`);
console.log(JSON.stringify(sourceFile.getStructure(), null, 2));

Actual behavior

The function overload for foo appears as a statement. This violates the type constraint of StatementStructures: the FunctionOverloadDeclarationStructure, with kind StructureKind.FunctionOverload, is not a valid statement per the definition of StatementStructures.

Notably, the overload structure appears twice: once as a previous sibling of the function declaration, and once in the overloads array of the function declaration.

{
  "statements": [
    {
      "isExported": false,
      "isDefaultExport": false,
      "typeParameters": [],
      "docs": [],
      "hasDeclareKeyword": false,
      "parameters": [
        {
          "name": "x",
          "type": "number",
          "isReadonly": false,
          "decorators": [],
          "hasQuestionToken": false,
          "hasOverrideKeyword": false,
          "kind": 30,
          "isRestParameter": false
        },
        {
          "name": "y",
          "type": "string",
          "isReadonly": false,
          "decorators": [],
          "hasQuestionToken": false,
          "hasOverrideKeyword": false,
          "kind": 30,
          "isRestParameter": false
        }
      ],
      "returnType": "void",
      "isGenerator": false,
      "isAsync": false,
      "kind": 14
    },
    {
      "name": "foo",
      "statements": [
        "void(x);"
      ],
      "parameters": [
        {
          "name": "x",
          "type": "number",
          "isReadonly": false,
          "decorators": [],
          "hasQuestionToken": false,
          "hasOverrideKeyword": false,
          "kind": 30,
          "isRestParameter": false
        }
      ],
      "returnType": "void",
      "typeParameters": [],
      "docs": [],
      "isExported": false,
      "isDefaultExport": false,
      "hasDeclareKeyword": false,
      "isGenerator": false,
      "isAsync": false,
      "kind": 13,
      "overloads": [
        {
          "isExported": false,
          "isDefaultExport": false,
          "typeParameters": [],
          "docs": [],
          "hasDeclareKeyword": false,
          "parameters": [
            {
              "name": "x",
              "type": "number",
              "isReadonly": false,
              "decorators": [],
              "hasQuestionToken": false,
              "hasOverrideKeyword": false,
              "kind": 30,
              "isRestParameter": false
            },
            {
              "name": "y",
              "type": "string",
              "isReadonly": false,
              "decorators": [],
              "hasQuestionToken": false,
              "hasOverrideKeyword": false,
              "kind": 30,
              "isRestParameter": false
            }
          ],
          "returnType": "void",
          "isGenerator": false,
          "isAsync": false,
          "kind": 14
        }
      ]
    }
  ],
  "kind": 36
}

Expected behavior

The overload should appear once, as a member of the function declaration's overloads array.

Obligatory ts-ast-viewer link

@ajvincent
Copy link
Contributor Author

I am seriously considering submitting a pull request to fix this, but I'd like some guidance, @dsherret, before attempting to do so. There's some nuance to this.

One aspect I noticed a couple days ago is that simply depending on OverloadableNode.getOverloads() or OverloadableNode.getImplementation fails right now for type definition files. The code for OverloadableNode depends on the presence of a function body, which we won't have in this situation.

@ajvincent
Copy link
Contributor Author

@ajvincent
Copy link
Contributor Author

ajvincent commented Mar 20, 2024

Some good news: ts-morph's structure printer rejects the overloads in the statements array when fed the same (albeit with a funny error message based on SyntaxKind rather than StructureKind). 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant