Skip to content

Design Meeting Notes, 11/16/2022 #51810

Closed
@DanielRosenwasser

Description

@DanielRosenwasser

Verbatim Import Syntax

#51479

  • importsNotUsedAsValues
    • Default is remove
    • Sometimes you don't want to elide the import
      • The module you're importing has a type, but also has side-effects.
      • preserve fixes this.
        • The named import is dropped, but the import statement is retained for side-effects.
  • preserveValueImports
    • Default is false
  • Wouldn't it be simpler to have a mode where whatever you write is what you get, and the only things that get dropped are type imports?
    • So import { blah, type foo } from "module" -> import { blah } from "module"
    • So import { type foo } from "module" -> import "module"
    • Technically this mode already exists - when you combine importsNotUsedAsValues: preserve and preserveValueImports: true with isolatedModules: true.
  • What's the const enum behavior?
  • Seems like simplifying is good, and this is what we wanted to ship originally - but are we forgetting the original use-cases? Also, we would be sending our users a lot of confusion/mixed messages.
    • Angular.js 1.x was a pretty big motivation.
      • Error mode was possibly a mistake - trying to signal "this is an unnecessary value import."
      • Maybe this should have been a lint rule.
  • There is positive feedback about deprecating the old options, providing a new one.
  • Second part of this proposal prohibits ESM syntax when targeting other module systems.
    • CJSish systems would need
      • Importing

        import fs = require("fs");
      • exports need to be export = { /* some object*/ }

      • Tradeoff - named imports in import {} = require(...) aren't supported.

      • Anecdotally, issues in CJS/ESM interop in nodenext are horrible - the resolution works, but the types inferred from the interop are extremely confusing.

  • We have consensus on the first part, not the second part being part of the same flag.

Require Literal Types to Have Value Overlap in Assignability with Enums

#51561

Today this is the situation in our main branch:

enum E {
    Foo = 1,
    Bar = 2,
    Baz = 4,
}

function f(e: E) {
    if (e === 7) { // disallowed
        // ...
    }

    e = 7; // allowed for some reason?
}
  • Tightened this up.
  • Breaks a lot in our compiler because of enums not declaring an explicit 0-like None value.
  • Having a computed enum member like enum E { Foo = Math.random() } allows it to be comparable to everything else.
  • But strange that you can't compare but you can assign. Seems bad.
  • New change require some overlap in the value domains when assigning.

Narrowing unknown-Originating {} Values with instanceof

#51014

Playground Link

function foo(x: unknown) {
    if (!!x && typeof x === "object" && "yadda" in x) {
        x.yadda
    //  ^?
    }

    if (!!x && x instanceof Object && "yadda" in x) {
        x.yadda
    //  ^?
    }
}
  • We think there are no issues in principle - but implementation consults the declared type which is inappropriate. You can end up with one of these unknowns in different ways
  • Discussion should follow outside of the meeting.

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