Skip to content

Design Meeting Notes, 9/22/2021 #46012

Closed
Closed
@DanielRosenwasser

Description

@DanielRosenwasser

Binding Pattern Breaking Changes

#45846 (comment)
#46009

  • Motivation

    declare function g<T>(): T;
    
    // Type is { x: any, y: any, g: any }
    // which is kind of dumb.
    const { x, y, z } = g();
  • Other more complex issues.

  • Why?

    • Best thing we can imagine is left-to-right completions for

      const { x, y, z } = { /*|*/ }
      //                      ^
      // We expect completions for x, y, z.
  • Current proposal is to disable for object binding patterns, but re-enable contextual typing from array binding patterns.

  • We still don't fully understand the inferences - probably best to do that.

  • When we started doing implied types from binding patterns, we didn't have types apart from any - now have never and unknown.

  • Let's do a full revert and think through this a bit more.

Node ESM Support

#44501
weswigham#67
weswigham#68

  • New resolution modes: node12 and nodenext

  • CJS and ESM files can resolve files via different paths based on the syntax and containing file.

    // Always follow CJS resolution
    import foo = require("foo")
    
    // Dynamic import - always follow ESM resolution
    const a = import("foo");
    
    // Always depends on the **containing file**!
    import * as a from "foo";
  • This is "solved" albeit complicated, but what is not solved is...

  • Import type syntax:

    type Foo = import("foo").Foo;
    • Can't disallow in CJS files because of existing CJS .d.ts files.
  • So how do you differentiate between "this should resolve as ESM vs CJS"?

    • Don't have any other syntax for inline type import syntax.
  • Could have a different conditions passed into import(...) types.

    • Like in an import assertion: import("foo", { /*conditions*/ })
  • Why does this matter?

  • Technically the MVP doesn't need to include this...but it will likely be an issue.

  • If you need to reference a type in ESM, either in .d.ts emit or by-hand, can you just write

    import "esm-file";
    • No, you can't :(
  • Can you lean on import() types always getting inferred from containing context?

    • Yes, you have to for compat, but you can't model a CJS file that actually import()s an ESM.
  • Import assertions affecting module resolution?

    • Seems like a no-no, but might need to use sibling conditions as a way to bypass that.

      type Foo = import("foo", { assert: { }, resolver: "esm" });
  • Heavy regret of not introducing require() types; now you need a "real import type" type.

  • Whole thing is such a 🤬😫😢😭

  • What if we just didn't let you write import in a non-module file?

    • Force users to write require() in CJS
    • Goes against a lot of expectations.
    • Isn't that what people want to write though?
    • What is the guidance? Users should use module: node12, but as far as they're concerned they're still doing CJS.
  • If our heads are spinning from this, users' will too.

    • A lot of concerns around complexity.
  • Stripping out complexity?

    • Export maps are complicated, but are a necessary feature for bridging the ESM and CJS worlds.
      • Trying to get it set up is rocket science, not supporting it would be worse.
  • "maybe I'm just old and grumpy"

    • "no this sucks"
  • We should be able to explain the happy path to people.

  • We have a lot of concern over how easily we'll be able to communicate best practices here; this is not just something that can affect TypeScript, the complexity can significantly hurt Node.js too.

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