Skip to content

Stop using "any" in the JS declarationsΒ #56618

Closed as not planned
Closed as not planned

Description

πŸ”Ž Search Terms

any, unkown

πŸ•— Version & Regression Information

Here it says in the TS docs:
"❌ Don’t use any as a type unless you are in the process of migrating a JavaScript project to TypeScript. The compiler effectively treats any as β€œplease turn off type checking for this thing”. It is similar to putting an ts-ignore comment around every usage of the variable. This can be very helpful when you are first migrating a JavaScript project to TypeScript as you can set the type for stuff you haven’t migrated yet as any, but in a full TypeScript project you are disabling type checking for any parts of your program that use it.

In cases where you don’t know what type you want to accept, or when you want to accept anything because you will be blindly passing it through without interacting with it, you can use unknown."

So why are there so many anys all over the codebase? If you're not going to use generics, at least use unknown. Yeah it might break something that was already working, but isn't that kinda the point? To make bad code not be allowed? And it's just TS, it won't actually break real code.

⏯ Playground Link

No response

πŸ’» Code

JSON.parse("1") // number, or unknown
[1].values().next().value // number
Array(1) // a generic, defaults to unknown

πŸ™ Actual behavior

JSON.parse("1") // any
[1].values().next().value // any
Array(1) // any[]

πŸ™‚ Expected behavior

JSON.parse("1") // number, or unknown
[1].values().next().value // number
Array(1) // a generic, defaults to unknown

Additional information about the issue

No response

Activity

  1. MartinJohns commented on Nov 30, 2023

    @MartinJohns
    Contributor

    Duplicate of #26188, and probably a few others (as this "bug report" is very unspecific).

  2. fatcerberus commented on Nov 30, 2023

    @fatcerberus

    it's just TS, it won't actually break real code

    I'm sure TypeScript devs everywhere will be happy to learn they haven't been writing real code all this time 🀣

  3. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    Martin Johns (@MartinJohns) What else is it then? The docs are saying you should never do this and then it does that in code that everyone will use. Using just one of the functions included in the standard library can leak anys everywhere if you're not careful. And it's a very unspecific issue, am I supposed to make an issue for each one? Because there are a huge amount of them everywhere.

  4. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    Bruce Pascoe (@fatcerberus) Yeah, I'm one and it isn't. I don't see any browsers or runtimes running TypeScript. Bun? That turns TypeScript into JavaScript, because it can't run TypeScript.

  5. fatcerberus commented on Nov 30, 2023

    @fatcerberus

    Yeah, I'm one and it isn't. I don't see any browsers or runtimes running TypeScript. Bun? That turns TypeScript into JavaScript, because it can't run TypeScript.

    If you think the fact that nothing runs TypeScript "natively" means TS can just introduce massive breaking changes and add new compiler errors to people's code willy-nilly, then yeah, this isn't worth engaging with further.

  6. MartinJohns commented on Nov 30, 2023

    @MartinJohns
    Contributor

    Software development is not black and white. There's not the one true statement for every case. The documentation is a general guideline.

    It's also a question of practicality. Changing this is a massive breaking change. And in some cases the any just makes more sense (e.g. for JSON.parse(), which is inherently type unsafe).

    And it's a very unspecific issue, am I supposed to make an issue for each one?

    That would be more practical than "don't use any anywhere". In some cases it's part of the declaration file (e.g. JSON.parse(), for which there exists many issues), and in another case you're talking about the fallback to any if a type can't be resolved (there exists an issue too).

    And you can be assured that the type is very well away of issues revolving around any and tries to eliminate it, within reason.

  7. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    Bruce Pascoe (@fatcerberus)

    TLDR: preventing bugs is really bad and the world will explode.

    Ok, and what's so bad about these breaking changes? Does it somehow make things not work anymore? Will every website on the internet crash? Will the issue be really hard to fix? Will it be a change that makes no sense? Will it make anything, at all, worse? It doesn't? Oh, it's now following the rules set forth by the docs? And it behaves as expected? And it will make the code more understanderable? And it will prevent bugs? And it's doing what TypeScript is supposed to do? If you're so ok with anys everywhere, why don't you just use it everywhere? Hell, why do even use TypeScript? Oh no, we're fixing a bug and some poeple might have to put in a little bit of effort so that their code works as they expected it to. "Willy-nilly". If you think that's "willy-nilly", you're not worth engaging with further. How do you not understand these basic TypeScript things? "breaking changes". This isn't Python, which also doesn't run natively, this will just prevent people from compiling their code. You still have the old code and that code still works. Nothing actually breaks. Here's the worst case scenario: there's a bug in the codebase. there's a change that prevents this bug. you might have to change your code to fix the bug. oh no, i had to fix a bug. literally the worst thing that can happen to you is that you have to fix a small bug. so terrible.

    I can't remember what you said last time I interacted with you, but if I was in charge of a big tech company, I'd make you be a manager.

  8. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    Martin Johns (@MartinJohns)

    I see you've read what I said to the other guy. This prevents people from writing bugs. You know what's a breaking change? "Uncaught TypeError: Cannot read properties of null (reading 'value')". No, any never makes sense. If it's so unsafe, then why is ok for it to be unsafe without any warnings whatsoever? If it's so unsafe, make it be unknown. In case you didn't know, unknown means you don't know what it is. Like what possible reason could you have for not at least making it be unknown? You keep saying random substanceless corporate gibberish.

    Why is it that whenever I speak to either of you, you both say the fucking stupidest things? "no preventing bugs is bad". "no it's not black and white". "oh no, we can only get rid of any within reason", "no it's just a general guideline". Man I could say 1 + 1 is 2 and you both would leave a comment other than saying yes. "if we made 1 + 1 be 2, it would break so much code. we can only make calculations be correct within reason. yeah i know not fixing this caused a hospital to blow up, but it would theoretically be possible that this change might accidently fix world hunger. I know this is breaking international laws and the Geneva convention, but those are just recommendations anyway. so if you make an indivual bug report for each any in the codebase, i will consider it (meaning i won't). that's because i somehow don't understand what TS is or how that preventing bugs is a good thing".

  9. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    Bruce Pascoe (@fatcerberus) Martin Johns (@MartinJohns)

    Preventing bugs is a bad thing right?

  10. fatcerberus commented on Nov 30, 2023

    @fatcerberus

    Yeah, this is getting out of hand. I fully expect Ryan Cavanaugh (@RyanCavanaugh) (the project lead) to lock this issue whenever he gets around to reading it.

    I'm just going to leave this here
    https://opensource.microsoft.com/codeofconduct/

  11. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    Bruce Pascoe (@fatcerberus)

    Oh no, someone doesn't agree with me and they're right! This is out of hand!

    Tell me, what are the consequences of fixing this? Like what is the worst thing that could happen from fixing this? Don't tell me how this is a breaking change, what will happen from it being a breaking change?

  12. somebody1234 commented on Nov 30, 2023

    @somebody1234

    Tufan Al-Aqsa (@coolCucumber-cat) hey, just pointing out that browsers can't run JS either! they actually run machine code

  13. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    somebody1234

    Are you 3 intentionally trolling? It's not relevant and you keep bringing it up for no reason. Neither do you understand it.

    The TypeScript bit of the code literally doesn't do anything. You can't print to the console, you can't add numbers, you can't have variables, it doesn't affect anything in the code. That's also in the docs. No TS should affect in the JS.

    Why is this so difficult for you all to understand?

    Are you trying to tell me if I put machine code in the script tag, it will do anything? Actually, they run with electricity.

  14. somebody1234 commented on Nov 30, 2023

    @somebody1234

    right, sorry, my bad... regardless, it's still true that browsers don't run JS - they turn it into a bytecode format first, which is what gets executed. JS can't print to the console, JS can't add numbers, JS doesn't have variables - it's all the bytecode instructions (and the underlying C++ implementation of each method, depending on the methods).

    IOW: just like how bun transpiles TS to JS in a just-in-time manner, the browser transpiles JS to machine code in a just-in-time manner (and the bytecode down to machine code as well). so i'm interested in learning what is the difference between zig doing the JITting (bun), rust doing the JITting (deno) and C++ doing the jitting (V8, JSCore)

  15. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    Bruce Pascoe (@fatcerberus) I haven't broken the code of conduct. It can't be, for example, not accepting constructive critisism, there isn't any. If all the critisism, you, Martin and Ryan have given me was constructive, I could have invented teleportation. You can never actually tell me what would be so bad about preventing these bugs, you just make up reasons for it.

  16. 4 remaining items

  17. somebody1234 commented on Nov 30, 2023

    @somebody1234

    Would it be bad for it to then actually work in the new version? No, clearly not.

    correct - it is not a breaking change, as there are not errors in a new version where there were none in a previous version.

  18. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    somebody1234 I thought you might say that. In case you're not intentionally winding me up, no, it doesn't dissappear. Like you said, it's now bytecode. And guess what bytecode and JS can do? Things. Like if I tell JS or bytecode to make the screen be blue, it can do that.

    Right now, write some TS code. Then compile it. What does it look like? Well, like this: "". Those are double quotes by the way, it looks like this: ''. Let me make it clearer by adding a comment: "// there is literally no code here. it can't do anything. if it breaks, nothing happens. worst case scenario, someone fixes a bug which actually maybe does affect something."

  19. somebody1234 commented on Nov 30, 2023

    @somebody1234

    Tufan Al-Aqsa (@coolCucumber-cat) in that case what is the difference between TS -> JS -> bytecode and JS -> bytecode? regardless, it is not the JS that is doing anything.

    console.log(1 + 1);

    note that this is valid TS code.

  20. somebody1234 commented on Nov 30, 2023

    @somebody1234

    a JS file containing "" would also do nothing, so i'm not quite sure what your point is.

  21. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    somebody1234 Let me rephrase that. v1 works as intended. v2 allows you to write code that blows up your compter. v3 doesn't let you blow up your computer. So v3 is clearly good, even though it's a breaking change.

    Wait, did you just imply that it would be fine if TS just allowed anything? Please say I'm misunderstanding you.

  22. somebody1234 commented on Nov 30, 2023

    @somebody1234

    Tufan Al-Aqsa (@coolCucumber-cat) no, i said that it would not be a breaking change on the TS side.

  23. somebody1234 commented on Nov 30, 2023

    @somebody1234

    addressing a few other points:

    Does it somehow make things not work anymore?

    only if noEmitOnError is set to true.

    Will every website on the internet crash?

    No, but plenty are written with TS, and it will be very difficult to work on them after upgrading their TS dependency.

    Will the issue be really hard to fix?

    Depends on the codebase size. Although, to be fair, this would be easy enough to "fix" with a codemod that adds as any to all JSON.parse (and the same for all other functions that return any).

  24. somebody1234 commented on Nov 30, 2023

    @somebody1234

    it's not in TS itself, and so it's not ideal in that respect. but a huge fraction of projects already use eslint, so I don't think it's a particularly high barrier

  25. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    somebody1234 Do I have to spell out everything for you? That's JS code in a TS file. "console.log(1 + 1)" is not TS code. It's JS code. And TS has nothing to do with that. TS cannot execute JS and JS cannot execute TS. other than enums or any old TS feature like that, write me some TS code (not JS), which actually does something. show me how to do "hello world" in TS. why should eslint be resposible for not doing the exact thing ts was supposed to do? "a huge fraction". yeah, not all. and i doubt most of them even have those features enabled. does that even fix the problem? it's not you using any, it's the standard library. if you could, what do you do? "as unknown"? that's hella confusing. especially in jsdoc and only typechecking. and this isn't even about dependencies, this is about the standard library. no dependencies here.

    oh no, it works as expected and we eliminated bugs.

  26. coolCucumber-cat commented on Nov 30, 2023

    @coolCucumber-cat
    Author

    Exetremely controversial opinion: bugs are bad and we should try to fix to them. if someone accidently writes bad code, we should try to prevent it. even if it breaks some code, that's a good thing because now people are aware of potential issues and can stop them. yeah, maybe it is a breaking change but Martin Johns (@MartinJohns) said "this aligns with the "Breaking Changes" section of the release notes", implying that updates sometimes include breaking changes. if breaking changes are so bad, why are we including it? that would make TS be even more hypocritical than saying any is bad and then using any everywhere. and the breaking change eliminates bugs too, so combined with the fact that they're allowed, it sure sounds like we should fix it.

  27. kalkronline commented on Nov 30, 2023

    @kalkronline

    it'd be strange if JSON.parse("1") gave a number type since that would only happen in cases where the string (the value) is predefined.

    JSON.parse should probably return unknown or some JSON type, i'm sure there are many TS projects that don't use it properly and end up accidentally introducing unsoundness. But TS should only make this change if they have a mechanism to do it in a way that would be backwards compatible. (probably over 90% of projects use this and would break)

    This is what I do to avoid the issues with JSON.parse bein any:

    type JSONValue = string | number | boolean | null | JSONObject | JSONArray;
    type JSONObject = { [x in string]?: JSONValue }
    type JSONArray = Array<JSONValue>
    
    /** Type safe version of JSON.parse */
    export const parse: (...args: Parameters<typeof JSON.parse>) => JSONValue = JSON.parse;
    
    /** Use when building a type narrowing function. */
    type FromJSON<T> 
        = T extends JSONValue           ? T
        : T extends Record<string, any> ? {[K in keyof T]: FromJSON<T[K]>} & JSONObject 
        : T extends (infer U)[]         ? FromJSON<U>[]
        : T
    
    // an example interface
    interface Person {
        Name: string
        Age: number
    }
    
    // an example narrower
    export function is_del_mesg(j: JSONValue): j is FromJSON<Person> {
        if (typeof j != "object" || j == null) return false; 
        if (!("Name" in j)) return false;
        if (typeof j.Name != "string") return false 
        if (!("Age" in j)) return false;
        if (typeof j.Age != "number") return false 
        
        return true;
    }
  28. locked as too heated and limited conversation to collaborators on Nov 30, 2023
  29. RyanCavanaugh commented on Nov 30, 2023

    @RyanCavanaugh
    Member

    Insulting other users is a code of conduct violation that will quickly earn you an org block, especially if your response to a CoC reminder is further insults.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions