Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Design Meeting Notes, 10/6/2021 #46247

Closed
DanielRosenwasser opened this issue Oct 6, 2021 · 2 comments
Closed

Design Meeting Notes, 10/6/2021 #46247

DanielRosenwasser opened this issue Oct 6, 2021 · 2 comments
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Oct 6, 2021

@andrewbranch took notes for the first two items of this meeting


Check for Array Constraints When Instantiating Mapped Types with any

#46218

  • Noticed an issue with Promise.all: Promise.all on any produces Promise<Record<string, any>> #46169
    async function foo(x: any) {
      let abc = await Promise.all(x);
      let oops: any[] = abc;
      // Error: Type '{ [x: string]: any; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 26 more.(2
    }
  • When you plug an any into a mapped type, you get a Record from string to any
  • Due to changes to Promise.all in 4.5
  • Proposal: if the thing we’re putting into T here is array-like, the output should be array-like too.
    declare function f<T extends unknown[]>(x: T): { [K in keyof T]: T[K] }
    f([1, 2, 3])
    f(null as any)
  • What's the equivalent of an any that's known to be an array? Or a tuple with a known arity?
  • With
    declare function f<T extends [unknown, unknown]>(x: T): { [K in keyof T]: T[K] }
    let x = f([1, 2,])
    let y = f(null as any)
    Almost feels like you should map over the constraint and return that?
    • If an any flows in, should you really say the output has the right arity?
  • Next issue:
    type Arrayish<T extends unknown[]> = { [K in keyof T]: T[K] };
    type Objectish<T extends unknown> = { [K in keyof T]: T[K] };
    // Should always produce array types, but can't get this to work
    type IndirectArrayish<U extends unknown[]> = Objectish<U>;
    declare let x: IndirectArrayish<any>;
    • Actually this would be really weird - the constraint type should maybe be considered local knowledge; a local artifact of Arrayish or Objectish. Is it a dynamic attribute of the instantiation? It would need to be carried in the type, and that's not how type instantiation works.
      • When we check Objectish<U>, we make sure that U extends unknown. Then, we instantiate with U, but there's no knowledge - well, I guess there could be - let's take it offline
    • Talking about generalizing this from arrays to tuples: it seems like you could generalize this to any base constraint.
      type Objectish<T extends { x: string}> = { [K in keyof T]: T[K] };
      declare let x: Objectish<any>; // could be { x: string } instead of { [key: string]: any }?

strictJsxAttributeChecks

#46229

  • Resistance to having a flag for this. Is it enough bang for the buck?
  • The loose checking of dashed properties is old kludge designed for data-*. You can declare that now. We could add that signature to React typings and remove the hardcoded support from the compiler instead of flagging it at all.
  • Whatever we do, the user could add support back on their own with the global JSX namespace.
  • Are we willing to take an external PR so we can experiment and see what breaks?
    • Still don't want a flag.
    • Maybe open to doing it unflagged if we see a lot of good come from it.
    • PRs welcomed, not committed.

Conditions of Destructured Variables

#46143

type Action =
  | { type: 'A', payload: number }
  | { type: 'B': payload: string };

function reducer(state: Whatever, { type, payload }: Action) {
  switch (type) {
    case 'A':
      payload.toFixed();
      break;
    case 'B':
      payload.toUpperCase();
      break;
  }
}
  • Want to be able to narrow payload based on narrowing type.

  • PR has this working.

  • When destructuring a parameter, we know that there are no aliasing situations. That helps with the implementation.

    • If you start out with an action and then destructure, that can be tricky.
  • We can narrow the group depending on whether it comes from a const or parameter, and the declared type of the binding pattern as a whole is a union, then we see if we can narrow the types based on other destructured properties.

    • We create a pseudo-object type which kind can discriminate on.
    • Binding element is now a pseudo reference.
  • Does modification reset narrowing?

    • Yes, only consts and unmodified parameters.
  • Relies on these properties coming from the same destructuring pattern.

  • So this doesn't work?

    const { kind } = action;
    const { payload } = action;
    
    if (kind === "A") {
        // payload ideally should be narrowed here.
    }
    • No - no ways we can do that.
    • However, we are able to narrow action by kind, which is nice.
    • Feels like a weird limitation.
@DanielRosenwasser DanielRosenwasser added the Design Notes Notes from our design meetings label Oct 6, 2021
@treybrisbane
Copy link

@DanielRosenwasser Just on mapped type behaviour with arrays/tuples: Have you guys at all considered having dedicated mapped type syntax for arrays/tuples? E.g. Something like [ [I in indexof SomeTuple]: SomeTuple[I] ]?

Not intended to be a feature request or anything. I'm mostly just curious if the idea of dedicated syntax has come up, as the interaction between the existing mapped types and arrays/tuples has always been a little quirky in my experience. 😄

@DanielRosenwasser
Copy link
Member Author

We did a while back - it was something that was discussed way back, and I was a proponent of it, but the idea that a mapped type on an array was so useless, in addition to the idea that you'd always have to add a conditional type to do the "right" thing, was something a lot of people on the team weren't big on.

@DanielRosenwasser DanielRosenwasser changed the title Design MeetingNotes, 10/6/2021 Design Meeting Notes, 10/6/2021 May 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Notes Notes from our design meetings
Projects
None yet
Development

No branches or pull requests

2 participants