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, 3/29/2019 #30645

Closed
RyanCavanaugh opened this issue Mar 29, 2019 · 0 comments
Closed

Design Meeting Notes, 3/29/2019 #30645

RyanCavanaugh opened this issue Mar 29, 2019 · 0 comments
Labels
Design Notes Notes from our design meetings

Comments

@RyanCavanaugh
Copy link
Member

Design Meeting Notes 3/29/2019

Safeness of indexed access types (#30603)

This code is patently unsafe:

function f2(obj: { a: number, b: string }, key: 'a' | 'b') {
    obj[key] = 123;
}

We need to get different types for reading and writing an indexed access type.

Also has implications for constraints and assignability

Consider this code:

function foo<T, K extends keyof T>(obj: T, key: K) {
    obj[key] = 123;
}

From a constraint perspective, the correct way to look at a reduction of T[K] is:

  • If T extends C, then we try to resolve T[K] using the constraint (possibly recursively)
    • Better form: During simplification, specify whether this is a simplification for reading or writing
      • Simplification today: T[A | B] simplifies to T[A] | T[B], which is only correct for reading
      • Similar: Given (T | U)[K], the read simplification is T[K] | U[K] and the write simplification is T[K] & U[K]
    • During assignability checks, simplify the source for reading and the target for writing
    • Once the unions, etc are removed via simplification, we still might have constraints
      • e.g. T[K] = S where T extends { a: string, b: number } and K extends keyof T
      • We need to pick the widest K ("a" | "b") and then distribute that (T['a'] | T['b']]) into the narrowest target value
      • Seems to work pretty well
    • In the unconstrained T case, what do we do?
      • Disallow assignment
    • What about T extends { [x: string]: any } ?
      • Is the intent that any assignment is legal here?
        • Seems bad?
    • What about T extends { [x: string]: number } ?
      • All writes via constraints are suspect...
        • Equally suspect?
      • Is T[""] = 0 OK or no?
        • 🤷‍
        • This is a subtyping violating if it's inconsistent with T[K] = 0

#30637

function print<T>(x: T): void {
    console.log(x.toString());
}

print(null); // A-OK!
  • This was OK because the default constraint of T is {} and {} acquires the Object apparent members.
    • (Non-SNC back compat accomplished by adding the Object apparent members back to unknown)
  • Now you have to write print<T extends {}> which becomes meaningful.
  • Some breaks in react-redux
  • lodash has some breaks where they seem to rely on {} coming from broken inference (wow)
    • Most changes are actually just different error spans
  • Back compat means what
    • Fix lodash and react-redux
    • Circular constraints keep hobbling on
  • Should we lint-ban {} in DT (in files with sufficiently-high version)?
    • Yes (use unknown or object or string | number | boolean | object | symbol)
    • "Goodbye {}, we hardly knew ye" - @rbuckton
@RyanCavanaugh RyanCavanaugh added the Design Notes Notes from our design meetings label Mar 29, 2019
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