Skip to content

Design Meeting Notes, 2/1/2023 #52579

Closed
Closed
@RyanCavanaugh

Description

@RyanCavanaugh
  • Intersection state Consistently propagate intersectionState in relations #52392
    • Unifies the interaction of excess property checking and weak types
    • Key logic is in structuredTypeRelatedTo, dealing with properties which are nested in the intersection, e.g.
      • { a: { x: string } } & { c: number } , we need to deal with both the intersection type and its final form
      • Contrast with something like { a: { x: string } } & { a: { y: number } } - a contextual-agnostic analyis can't handle this correctly
      • Interacts with isDeeplyNestedType, which exists to prevent runaway stackoverflows in generatively-recursive types
        • The "identity key" here is, for example, the symbol of a declared type
        • For intersections, no such durable/reusable identity key existed
        • This meant we couldn't safely plumb to more than a fixed depth (1) of intersections when looking for excess properties
      • Fix: Instead, an intersection is deeply nested if any of its constituents is deeply nested
        • Now we don't need a fixed depth limit
      • Fix is good, everything's passing
      • Check time for vuelidate on DT has doubled, but really only because we're doing work we should have been doing the whole time
      • 5.0 or 5.1?
        • It's a bugfix, standard level of riskiness, 5.0.
  • Widening/nonwidening enum literals Widening and non-widening computed enum types #52542
    • In 5.0 we unified enum logic, yay
    • Consider enum E { A = 1, B = 2, C = 3}
      • Type E is a union, E.A | E.B | E.C
    • Contrast enum X { A = compute(0), B = compute(1), C = compute(2) }
      • Old behavior: type X is just X, a subtype of number
      • New behavior: type X is a union of X.A | X.B | X.C, pretty much the same as E, each of which is an opaque subtype of number
    • All motivating scenarios that led to fresh/nonfresh widening/nonwidening literal types for string/numeric literals now apply to these opaque (nonliteral) types
    • e.g. let a = E.A;, a = E.B; should be legal
    • Declaration file emit allows for initializers so that you can get both behaviors despite the fresh and nonfresh types having identical names
    • 👉 5.0
  • export ordering (TC39 update)
    • Order 1: @decorator export class X {
    • Order 2: export @decorator class X {
    • Order 1 is the longstanding order in TS
    • Order 2 came into existence due to a transcription error when writing the proposal
    • Upon fixing the error, concerns were raised
      • What if you want to "decorate an export" ?
        • What does this mean?
          • Sort of unclear, all possible things you could do here violate critical static invariants
      • Various arguments ad linguistics of what's an adverb, adjective, conjunction junction what's your arrow function, etc.
      • What if you want to have different behaviors between Order 1 and Order 2?
        • But what?
        • At best, you could have the inner and outer names of a class refer to the undecorated / decorated values, but this is a footgun
          • If desired you can use proxies
        • If this is legal, then @deco1 export @deco2 class A { becomes legal and sensical (!)
    • TC39 Discussion continued for a long time without progress
    • Decorators went to stage 3 without this being addressed
    • Today
      • export @decorator class is legal per TC39
      • In 5.0 today:
        • In TS files, both orderings are supported with identical semantics
        • In JS files, only export @decorator class is supported under non-experimental-decorators
    • This has implications for Function#toString since decorators are supposed to be part of toString but not export
      • Arguments about eval(someClass.toString()) but this is not an existing invariant anyway (?)
    • Do we need a transitional flag?
    • Quickfix? Tool? Regular expression?
      • These tools don't work on documentation on the internet
        • This is an argument for making the proposal change, not making the behavior available in TS when it doesn't actually exist
    • What are other transpilers doing?
      • If we allow this (illegal!) syntax, then every TS-compatible transpiler has to as well, and it's a de facto JS feature
      • But it's effectively moot since (all?) transpilers already presumably support experimentalDecorators
      • Babel issues a specific error
    • Conclusions:
      • Hope that both-orderings proposal goes through at TC39 and we don't have to make a tough decision
      • Otherwise, circle back and argue about allowing flagged, unflagged, or not at all
    • Update 2/2/23: Most of this turned out to be moot because both orderings were accepted at TC39 today 🎉

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design NotesNotes from our design meetings

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions