Skip to content

Design Meeting Notes, 12/1/2023 #56641

@DanielRosenwasser

Description

@DanielRosenwasser

Ignoring undefined/null types fed into keyof

#51331

  • Intersections of undefined and object types get evaporated away.

    type Foo = { x: string } | undefined;
    type Bar = { y: string };
    
    type FooAndBar = Foo & Bar;
    //   ^? { x: string } & Bar
    // No `undefined` because `undefined & Bar` is `never`
  • Okay, what's the problem?

    type Foo = { x: string } | undefined;
    type Bar = { y: string };
    
    type KF = keyof Foo;
    type KB = keyof Bar;
    
    type K1 = keyof (Foo & Bar);
    //   ^? "x" | "y"
    type K2 = keyof Foo | keyof Bar;
    //   ^? "x"
  • Uh oh.

  • Could make the argument that keyof (T | undefined) should probably just be keyof T - if you have a type like keyof (T | undefined), being able to actually index into a T depends on actually being able to do something with the T itself.

  • You can already write (T | undefined)[keyof T] in type space without any issues. So the idea of (T | undefined)[keyof (T | undefined)] being allowed makes sense.

  • Are we sure we're not saving someone from a mistake?

    • Feels like as long as you're preventing the indexing in the value space, that's where the value is.
  • Seems reasonable, we'd like to experiment with that.

  • [[Revisiting - the getProp function actually doesn't make enough guarantees for us to do this safely.]]

    function getProp<T, K extends keyof T>(obj: T, key: K) {
        return obj[key]; // allowed!
    }
    
    let obj: { foo: string } | undefined
    getProp(obj, "foo"); // uh oh!

Node.js module interop changes

nodejs/node#50981
nodejs/node#50096

  • Prologue directive to specify to Node what named exports a CommonJS provides.
  • Node can't do the same analyses that bundlers perform, so this directive is intended to help here.
  • Gives CJS modules a path forward for compat.
  • Maybe not too bad because we serialize __esModule markers.
  • For our emit, specifying these when given as inputs would "just work" because we preserve all prologue directives.
  • The fact that this is in a JavaScript file complicates things for us. We would need to see some sort of marker in the .d.ts file.
    • Or we would need to resolve the JavaScript file and scan prologue directives.
  • Apart from the complications, we are not a big fan of adding more and more and more and more to try to fix CJS/ESM interop. Every fix is another edge case for devs. It continues to complicate the options and configuration people need to manage.

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