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

cutting back scope #217

Open
nektro opened this issue Apr 16, 2024 · 14 comments
Open

cutting back scope #217

nektro opened this issue Apr 16, 2024 · 14 comments

Comments

@nektro
Copy link

nektro commented Apr 16, 2024

I think a first iteration of this proposal should limit itself to only the values from typeof, arrays, and classes in function parameter / variable / class field definitions. maybe the ?: and !. syntax too. this would provide an a common base that's easy for engines and tools to adopt while still being enough to bring immediate benefit to developers.

the readme goes into great depth about prior art but I dont think we should worry about tying ourselves strictly to being source-compatible with TypeScript due to the reasons y'all already have listed wrt standardization and not breaking the web. even though they and others have done a great job paving the road.

I also agree with engines ignoring the types at runtime while making the types available to tooling being invaluable.
and that putting the types in-source is much better than in-comments.

type declarations etc massively increase the scope and potential ambiguity in the syntax. I think it would be very beneficial to developers and the prospects of getting this landed if we started much smaller and added other features in future proposals.

great work getting this to stage 1 and I'd love to help out materially where I can to help this along :)

@nektro
Copy link
Author

nektro commented Apr 17, 2024

TypePrimitive:
  undefined
  object
  boolean
  number
  bigint
  string
  symbol
Type
  TypePrimitive
  TypePrimitive [ ]
TypeAnnotation:
  ?(opt) : Type
LexicalDeclaration:
  LetOrConst Identifier TypeAnnotation(opt) Initializer(opt)

@nektro
Copy link
Author

nektro commented Apr 17, 2024

FieldDefinition:
  ClassElementName TypeAnnotation(opt) Initializer(opt)

@nektro
Copy link
Author

nektro commented Apr 17, 2024

production OptionalAssertion would be quite similar to OptionalChain but with ?. swapped for !.

@conartist6
Copy link

I'd be in favor of this proposal so long as the types are checked at runtime. It's the only way you can be sure what the correct "JS type" is for something, and thus it's the only way to give the real words meanings.

@conartist6
Copy link

conartist6 commented Aug 10, 2024

Otherwise what would stop me writing this:

const foo: string = 5;

Remember this wouldn't be a coercion or an error: just an outright lie, and one that you have no spec-based grounds to reject as invalid.

@conartist6
Copy link

conartist6 commented Aug 10, 2024

Without any specification-based grounds to push back on such type lies, it would not be possible to use these annotations as a source of factual information to build better tools.

@nektro
Copy link
Author

nektro commented Aug 10, 2024

Otherwise what would stop me writing this:

tooling would tell you its wrong. there's notes in the README that the engines noticed that in practice the annotations werent really necessary in practice to generate performant code

@shaedrich
Copy link

shaedrich commented Aug 14, 2024

tooling would tell you its wrong

If tooling is used. Having types and using tools are two separate things. But that is a debate on principles (see #205) and this issue probably isn't the place for this, as smarter people than me have their reasons for not going down this road.

@conartist6
Copy link

conartist6 commented Aug 15, 2024

tooling would tell you its wrong.

The situation for the person who develops the code remains wholly unaffected by this proposal. They see the same types they always saw, and they are still the only person who can get tooling feedback on the validity of those types.

Once the code has been divorced from its tooling and shipped, there will be no more chance of interpreting the types correctly or extracting meaningful information from them. So the person shipping the code gains nothing, and the person running it loses value.

@spenserblack
Copy link

spenserblack commented Aug 15, 2024

I've asked this a few times when runtime type checking is mentioned, but I'll ask it again: what happens with large and/or deeply nested types?

const sum = (numbers: number[]): number => // ...

Now I call this function with a hard-coded value, e.g. sum([1, 2, 3, /* ... */ Number.MAX_SAFE_INTEGER]). Will the runtime typechecker traverse the entire value just to ensure that every single property matches the type signature? This can be really expensive at runtime. I'm limiting myself to the simple types defined in this comment, but this can be way more expensive with complex types.

These simple examples might seem absurd, but this can become a real issue. For example, reading JSON from an API. Are you saying that the runtime typechecker would need to assert that all of the data matches the type to ensure the nth value isn't a "type lie", instead of just allowing the developer to "trust" that the type will be as expected (assuming no error response)? If I'm reading a large amount of data, and possibly multiple pages of that data, do I really want the runtime to implicitly type-check all of that data just because I added an annotation?


Once the code has been divorced from its tooling and shipped, there will be no more chance of interpreting the types correctly or extracting meaningful information from them. So the person shipping the code gains nothing, and the person running it loses value.

Even if the types aren't asserted at all, here's what one gains from annotation:

  • Code editors can provide better suggestions
  • Documentation generators can read the annotations and provide the expected types, making documentation much more navigable
  • Code can become more readable. For example, if I ask you "is this supposed to be an array of numerical IDs or UUID strings?" you should be able to figure that out from this type annotation: const ids: number[]. Note that I said supposed to (developer intent, not actual behavior)

In fact, using TypeScript with Vue + Vite does not assert types for the dev server1. In my personal experience, the improved type hints are what I benefit from during development, and I don't suffer from a lack of type assertion.

Remember this wouldn't be a coercion or an error: just an outright lie

Without any specification-based grounds to push back on such type lies, it would not be possible to use these annotations as a source of factual information

Can I lie with un-asserted type annotations? Sure. I can lie like this in Python as of 3.12:

# Python
def get_number() -> int:
    """
    Totally gets an int!
    """
    return "one"

I can also lie in some form or another in nearly any language:

// Go

// GetNumber safely gets a number, and will totally not panic.
func GetNumber() int {
    panic("Pranked! I lied to you.")
}
// Rust

/// Returns `true` if `n` is greater than zero
fn greater_than_zero(n: i32) -> bool {
    // Oops!
    n < 0
}

I can even make a "type lie" in TypeScript itself.

// TypeScript
const n: number = "one" as unknown as number;

Making sure that you're not "lying" falls under the realm of testing. A type annotation, like documentation and variable names, communicates the developer's intent. Testing asserts if they are "lying" or not. And if you do find type checking to be useful, it's better to do it once, at compile-time. Instead of forcing everyone running the code to spend additional computation time asserting the types at runtime, have the writer(s) assert types on their device(s) at compile-time.

Footnotes

  1. https://vuejs.org/guide/typescript/overview#overview

@mstoecklein
Copy link

mstoecklein commented Sep 11, 2024

Runtime type checker is a good idea, but please not in a production environment. This is something that can be an option (i.e. checking a box in the devtools). In case it's enforced on all scripts I can already see the performance issues. It's really not the responsibility of the runtime environment.

@jeswin
Copy link

jeswin commented Sep 18, 2024

I think a first iteration of this proposal should limit itself to only the values from typeof, arrays, and classes in function parameter / variable / class field definitions. maybe the ?: and !. syntax too.

Then this would be useless in nearly all codebases I've seen. Flow and TS have been around for long enough and developers have clearly voted for the level of expressiveness they'd like to see. If you fall too short, there won't be enough adoption.

@nektro
Copy link
Author

nektro commented Sep 18, 2024

something "winning" means it marketed and timed itself in a way to get the network effect, not necessarily that its superior. adding Flow or TS to vanilla ecmascript essentially wholesale would be an awful idea for many many reasons

@shaedrich
Copy link

shaedrich commented Sep 18, 2024

Then this would be useless in nearly all codebases I've seen.

The whole thing is useless without any additional tooling. Not to say, problematic in some aspects as others have already mentioned.

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

6 participants