Skip to content

Declaration file not workingΒ #60670

Closed
Closed

Description

@dpwzone

πŸ”Ž Search Terms

"d.ts", "d.ts file", "d.ts var", "d.ts declare var"

πŸ•— Version & Regression Information

New to typescript

⏯ Playground Link

No response

πŸ’» Code

Inside 'index.d.ts' file, following the same structure as 'Function' (lib.es5.d.ts - lines 275-319):

interface Test<T> {
  prototype: any;
}

interface TestConstructor {
  (value: string): Test<T>;
  readonly prototype: Test<T>;
}

declare var Test: TestConstructor;

Tried making the TestConstructor generic too (TestConstructor), but that made no difference.

Inside test-lib.ts file:

  test(): void {
    const foo: Test<Foo> = (value) => {

    }
  }

πŸ™ Actual behavior

Typescript complains about the value being an 'any' type inside the test() function
Image

πŸ™‚ Expected behavior

Expected TypeScript to know that value is a string, given it's defined in the 'index.d.ts' file. When looking for the type definition, it finds it, just like it does for 'Function'
Test:
Image
Function:
Image

Additional information about the issue

No response

Activity

  1. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    You need to turn off skipLibCheck if you're hand-authoring .d.ts files. There's no T in scope in TestConstructor.

  2. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    Doesn't that diminish type-system accuracy? That doesn't seem to be a good route.

    In hopes to track down the issue, I even removed all generics from the 'Test' type, but that didn't make any difference.

    interface Test {
    
      prototype: any;
    }
    
    interface TestConstructor {
      (value: string): Test;
    }
    
    declare var Test: TestConstructor;

    No difference, still seeing:
    Image

  3. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    The code is still wrong. You need const foo: TestConstructor = if you're expecting a contextual type there.

  4. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    The code following the exact same structure as 'Function', located in lib.es5.d.ts - lines 275-319.

    Image

    Are you saying the lib.es5.d.ts file is wrong too?

  5. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    It looks like this is a question rather than a bug report. This issue tracker is for tracking bugs and active work on TypeScript itself, rather than a general forum for programmers using TypeScript to get help or ask questions.

    You can ask questions on sites like Stack Overflow. We are not able to provide one-on-one support on the issue tracker. Please read the issue template carefully - it has important information on what kinds of reports can be acted on here, as well as links to useful TypeScript resources. Thanks!

  6. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    Respectfully disagree. This is definitely a bug, given our files don't follow suit with how TypeScript files operate.

    Image

    Image

    Given there is no difference between these 2, there is definitely a bug involved.

  7. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    Function is a special global type that has effects on function expressions. TestConstructor isn't.

  8. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    Yet, the code for 'Test' follows exactly how 'Function' is written.

    Given that, the 'Test' type should also be a 'special global type', right?

    This is definitely a bug.

  9. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    You have almost certainly not found a bug that hundreds of thousands of other developers missed over the course of the last decade. Can you just post a full sample of what you're trying to do?

  10. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    You have the relevant code. Given you're a development lead for typescript, it should be easy for you. Why is 'Test' not treated the same way as 'Function'?

    By the way, I have written 100s of libraries, many of which are used by 3 Fortune 500 companies, over my 30+ years of being a developer. Never did I poke fun at developers who asked questions. I find your tone very offensive.

  11. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    Completed? Is that how you all handle bugs? No wonder the development community dislikes typescript.

  12. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    I'm not able to help any further here without the requested self-contained code sample. I've already indicated two different fixes you needed to make to have the code be correct.

  13. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    The first "fix" diminishes type-system accuracy. Not really a fix, now is it?

    The second "fix" isn't a fix. You're telling me that I have to use the 'TestConstructor' instead. Why doesn't the 'var' approach work, like it does with 'Function'?

    Please don't 'complete' the issue, until the issue is actually complete.

    There is something functioning differently in my code, even though it's a straight copy of TypeScript's code. This is a bug.

  14. 9 remaining items

  15. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    It's special because only the global type Array<T> is the one that's applied to array literals. Only the global type Function gets applied to function literals. You can't create "new" ones that get literal-related behavior.

    Your original bug was an unexpected implicit any and I still have not seen a working demonstration of that. Can we get back on-topic?

  16. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    Odd, I supplied the code. Here it is again:

    interface Test {
    
      prototype: any;
    }
    
    interface TestConstructor {
      (value: string): Test;
    }
    
    declare var Test: TestConstructor;

    Image

    I'm almost ready to give up on this, as I'm able to extend 'Function' with the 'and' method without issue. Doesn't speak highly about type safety (restricting the extension method to my type, not the function type), but then again, you had already suggested that I "skipLibCheck", so I take it type-system accuracy isn't high on the list for TypeScript developers.

    I couldn't imagine how bad it would be in C#, if a developer wrote a 'sum' extension method on Object, instead of constraining it to a numeric type... true.sum(); lol

    From what I see online (stack overflow, etc.), this is why so many developers warn the community to stay away from TypeScript. The documentation is worse than Java's (lol), and trying to do something "simple" ends up being a nightmare. Too many times, I've read developers saying they had to produce hacky code to get it to work "properly".

  17. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    In extensions.ts file:

    declare global {
      interface Function {
        and<T>(source?: ISpecification<T>): ISpecification<T>;
      }
    }

    In specification.ts file:

    export interface ISpecification<T> {
      (root: Root<T>, query: CriteriaQuery<T>, builder: CriteriaBuilder): Predicate;
    }

    In service.ts file:

    const mergedSpecification: ISpecification<WeatherForecast> = specification1.and(specification2);

    Sad thing is, this works. But as stated before, 'and' is inside the 'Function' interface.

  18. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    You're expecting spooky action at a distance here. There's no real relationship between Test and TestConstructor in this code. Writing declare var Test: TestConstructor doesn't do anything at all.

    In the line const foo: Test, Test refers only to the type Test (which only has a prototype property, no call signatures, thus implicit any). There's no special sauce that makes Foo and FooConstructor be related -- it doesn't even have this effect in the global scope either.

    I really recommend reading something like the TypeScript Handbook to get a basic understanding of the relationship between types and values. The global scope declarations are quite complex, spread across multiple files, and written in a special way to allow for easier interface merging. You won't have a good time trying to learn the language by copying these declarations without understanding them.

  19. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    No relationship between 'Test' and 'TestConstructor'?

    When I click on "Go to Definition" of 'Test', the IDE shows:
    Image

    Is the IDE wrong? If there's no relation, than the Definition of 'Test' should only be the interface.

    Should this bug go to the VS developers instead?

  20. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    No relationship between 'Test' and 'TestConstructor'? Doesn't the "declare var Test: TestConstructor" create this relationship

    declare var Test: TestConstructor declares the existence of a variable called Test with the type TestConstructor. That's it. End of list. Nothing else. People really like languages like TypeScript that don't do spooky action at a distance.

    You're expecting that at const foo: Test, Test gets looked up as the value Test (thus resolving to the variable), and then that to go to the output of the constructor function, and for that to be consulted instead. But TypeScript has straightforward semantics: Test refers simply to the type Test, which you declared as interface Test { prototype: any }.

    The global types like Array and Function define three things:

    • The types themselves which are the types of the corresponding values (Function)
    • The types of the constructors which create them (FunctionConstructor)
    • The value that is the global variable you see in expression code (var Function: FunctionConstructor)
  21. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    Not sure if you saw the screenshot above, but when I click on "Go to Definition" for "Test", VS shows:
    Image

    If the interface is the only definition, then why do both the interface and variable show up as definitions in VS?

    As asked before, should this bug be submitted to the VS developers instead?

  22. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    "Find All References" intentionally looks for both value and type meanings of the same identifier since it's generally more useful to see more references rather than fewer. This behavior is due to user feedback and is intentional.

  23. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    "Find All References" is separate from "Go to Definition":
    Image

    I was referring to "Go to Definition".

    Just for laughs, I added another declaration right above the 'TestLib' class:
    Image

    Surely if what you were saying is correct, 'Test' should show up 3 times when I "Go to Definition", right?
    Image

    Yet, it doesn't.

  24. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    "Go to Definition" shows you all definitions of the identifier too. Imagine if you had written

    export { Test }

    you'd be exporting both the type and value meanings of Test, which are located at different places. Rather than having "Go Definition" show you different results depending on where you invoke it, which would be confusing, we consistently show all definitions of the specified identifier.

  25. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    Just added that.
    Image

    Made 0 difference, VS still only shows the 2 "definitions" when clicking on "Go to Definition", and it still doesn't even pick up the 3rd declaration I added directly above the 'TestLib' class (screenshot above)
    Image

  26. RyanCavanaugh commented on Dec 3, 2024

    @RyanCavanaugh
    Member

    I can't guess what the rest of your code is, nor do I enjoy transcribing screenshots. Please paste the whole contents of the file, what you invoked where, and I can check it. Thanks!

  27. dpwzone commented on Dec 3, 2024

    @dpwzone
    Author

    The TypeScript I provided IS what is in the file, not sure what else you're looking for. I tried making it as simple as possible, just for this purpose.

    Steps to reproduce what I have:

    1. Create a new project in VS
    2. Add a ts file with the following:
    declare global {
      interface Test {
        prototype: any;
      }
    
      interface TestConstructor {
        (arg: string): Test;
      }
    
      var Test: TestConstructor;
    }
    export {}
    1. Add another ts file with the following:
    class TestLib {
      test(): void {
        const foo: Test = (value) => {
    
          ...
        }
      }
    }
  28. locked as resolved and limited conversation to collaborators on Dec 4, 2024
  29. RyanCavanaugh commented on Dec 4, 2024

    @RyanCavanaugh
    Member

    That behavior was explained earlier. I think we've covered everything here. Please log a new issue if you have something actionable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions