Skip to content

Design Meeting Notes, 1/19/2018 #21307

@DanielRosenwasser

Description

@DanielRosenwasser

Conditional Types

  • Last time, we needed an idea of when to defer the evaluation of each branch of a conditional type.
  • Idea:
    • spread over unions, if you have any or never, you create a union (since you have no idea where anything will go)
    • If the type is assignable, go to the true branch's type.
    • Otherwise, check whether the type is not possibly assignable, then go to the false branch's type.
      • Type parameters imply the possibility of assignability - erase them to any.
        • What about never instead of any?
          • any works better for contravariant positions.
      • Uses typeMaybeAssignableTo which is like comparability but only at the top-level.
        • Should probably be a new type relationship.
        • Why not use comparability?
          • Ehh, not quite the same.
    • What happens when you can't make a definitive statement about either case?
      • We have to put in some new concepts of how to relate these types.
  • Also: new internal type called a substitution type.
    • In T extends string ? [[A]] : [[B]], you want A to act as something that is also a string in [[A]].
type Diff<T, U> = T extends U ? never: T

Core idea here is that in each branch, once the condition can be "evaluated", T is re-bound to each constituent if the original T was instantiated with a union type.

Means that

interface Box<T> {
    element: T;
}

type BoxEverything<T> = T extends any ? Box<T> : never;

// Same as 'Box<number> | Box<string> | Box<boolean>'.
type Foo = BoxEverything<number | string | boolean>;
  • Should T refer to the original type, or just the constituents?

    • Well, we could say that users need to make distribution over unions explicit.
    • Would need a syntax for iteration over unions.
      • P in T: P extends U ? P : never
    • We've very rarely not wanted the current behavior that automatically distributes over unions.
  • Seems like we want to do this!

    • Types continue operating on the principle of distributing over unions. We should find ways to communicate this to our users.
    • But wanting mapping, seems like we'd want to
  • Do we want to add the helpers to the standard library?

    • Definitely Diff.
      • But it doesn't actually have the ability to negate assignability.
    • What about If, Not, And, and Or?
      • "Yeah, but who's gonna use them?"
        • "Uhh...", [[collective laughter implying that somebody will use these for something crazy]]
      • What about NonNullable?
        • That leads us to the next topic.

Narrowing type parameter constraints

#21182

  • Want to narrow the constraint of a type parameter from number | undefined to number.
    • Conclusion: Experiment with offline.

Variadic Types

  • 13 minutes left in the design meeting, we can't reasonably go over this.

Optionality: missing and undefined

  • Comes up very frequently in React's setState API.

    • Users say "you should be able to pass in a subset of the properties in T (i.e. Partial<T>, meaning T but all optional) but you shouldn't be able to pass in undefined.
    • Currently the type system doesn't know how to differentiate these cases.
  • Today, the type hierarchy looks something vaguely like

            any
        /    |    \
       {}  null undefined
    
  • Could imagine a new subtype of undefined called missing!

            any
        /    |    \
       {}  null undefined
                    |
                missing
    
  • undefined is not assignable to missing, but the opposite is true.

  • Optionality implies unioning the type with missing.

    interface Foo {
        x?: number; // implicitly has the type 'number | missing'.
    }
  • Note! We don't want any to be assignable to missing!

    • any continues to be the top type (missing is assignable to any...) but is no longer quite the bottom type with respect to assignability (any is not assignable to missing!).
    • never continues to be the true bottom type, assignable to missing and everything else.
  • This would definitely be a breaking change.

    • What would Partial become?
      • Might need an Optionalize or Subset or whatever.
  • What about parameter types?

    • Often need to communicate optionality from a set of parameters to another set of parameters.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design NotesNotes from our design meetings

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions