Skip to content

Design Meeting Notes, 5/14/2021 #44097

@DanielRosenwasser

Description

@DanielRosenwasser

ES Modules in Node

https://gist.github.com/weswigham/22a064ffa961d5921077132ae2f8da78

  • export maps and .d.ts files

    • The same way we let you file a types field to reflect the main, we should have a "types" condition in your export maps.

      {
          "exports": {
              "./": {
                  "import+types": "./ts/esm/index.d.ts",   // <- this reflects the types you get for an import
                  "require+types": "./ts/cjs/index.d.ts",  // <- this reflects the type you get for a require()
                  "import": "./esm/index.js",
                  "require": "./cjs/index.js",
              }
          }
      }
    • Alternatively, "nested conditions" approach

      {
          "exports": {
              "./": {
                  "types": {
                      "import": "./ts/esm/index.d.ts",   // <- this reflects the types you get for an import
                      "require": "./ts/cjs/index.d.ts",  // <- this reflects the type you get for a require()
                  },
                  "import": "./esm/index.js",
                  "require": "./cjs/index.js",
              }
          }
      }
  • typesVersions?

    • Version specifier in the exports map?

      {
          "exports": {
              "./": {
                  "import+types>4.4": "./ts/esm/index.d.ts",
                  "require+types>4.4": "./ts/cjs/index.d.ts",
                  "import+types": "./ts4.4/esm/index.d.ts",
                  "require+types": "./ts4.4/cjs/index.d.ts",
                  "import": "./esm/index.js",
                  "require": "./cjs/index.js",
              }
          },
      }
      • Keeping it like this has the benefit of keeping things up to date.
  • Do we expect these exports to be written by hand?

    • Generally, yes.
  • This is all quite a lot of complexity.

    • Most people won't need multiple entry points and the like.
  • typesVersions was explicit, this isn't.

  • It's not necessarily just about ESM imports vs CJS require.

    • It's also about Node vs. the browser.
      • Also maybe about ES5 vs ESNext
    • There's value in the fact that you can nest these in flexible ways.
    • import+types>4.4 seems a little bit confusing, maybe "abusive" of the export map syntax.
    • Spec kind of expected identifier-like strings.
      • This behavior is relied on specially - for example, anything starting with a . is a path, anything not is "special".
    • Make sure people involved in Node take a look.
    • (side note: be cognicent of people importing .d.ts files like assets?)
  • Seems like team slightly prefers nesting, not concatenating (e.g. yadda+types)

    {
        "exports": {
            "./": {
                "types": {
                    "import": "./ts/esm/index.d.ts",
                    "require": "./ts/cjs/index.d.ts",
                },
                "import": "./esm/index.js",
                "require": "./cjs/index.js",
            }
        }
    }
    • But still need to check how that works for versioning.
    • Versioning?
      • typescript@>=4.4

      • types>=4.4

      • What about

        {
            "exports": {
                "./": {
                    "types": {
                        "import": "./ts/esm/index.d.ts",
                        "require": "./ts/cjs/index.d.ts",
                    },
                    "typesVersions": {
                        ">=4.4": "..."
                    },
                    "import": "./esm/index.js",
                    "require": "./cjs/index.js",
                }
            }
        }
        • Doesn't make sense because there's multiple ways to specify versioning in this manner.
    • If you care about versions older than whatever TypeScript supports this, you'll still need a top-level typesVersion.
    • Can't omit support for typesVersions from the MVP, otherwise users have to specially support the MVP in a weird way.
    • Leaning towards
      {
          "exports": {
              "./": {
                  "types": {
                      "import": "./ts/esm/index.d.ts",
                      "require": "./ts/cjs/index.d.ts",
                  },
                  "types<=4.5": {
                      "import": "./ts/esm/index.d.ts",
                      "require": "./ts/cjs/index.d.ts",
                  },
                  "import": "./esm/index.js",
                  "require": "./cjs/index.js",
              }
          }
      }
    • "types<=4.5" or "types@<=4.5"?
      • types@* vs types*?
        • You'd just write types.
        • But it's usually a semver pattern.
        • Need something that separates the semver pattern.

Breaking Changes

#44093

  • We'll look into this.

#44092

  • Change in inference.
  • We'll look into this.

#44087

  • Issue is that we look for all things that number is assignable to, reduce everything.
  • In theory, should reject the assignment.
    • So inclined to say "won't fix" - weirdness is caused by a bad assignment.

#43877

  • Bloomberg found the cause internally.
  • Without a minimal repro, can't improve anything.

unknown in catch

#41016
#41013

  • People liked unknown in a survey.
  • But it sucks to turn on in the TypeScript codebase.
    • What do you mean by it "sucks in the TS codebase?"
    • Lots of well-working code that doesn't improve.
    • "I'm willing to do the feature, I'm not willing to be the one who converts the TypeScript codebase to use it."
      • Like all good strictness flags.
  • Seems wrong that we don't complain about that loose any under strict.
  • Can always do a refactoring to migrate an existing codebase to use : any in catch clauses.
    • That helps us feel okay with putting this under --strict.
  • Would be great to have a way to say "the only thing this throws is Error".
    • Agreed, but no way to do that today.
    • Could totally imagine a thing that asserts the type of the error thrown.
  • Seems like we're okay with this flag going under --strict.

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