Skip to content

Design Meeting Notes, 2/9/2018 #21838

Closed
Closed
@DanielRosenwasser

Description

@DanielRosenwasser

Type Operators

  • Not crazy about giving these things names that people've been using.

  • Not crazy about Diff

    • Semantics are fuzzy between "union member" diff and "object member" diff.
  • Ideas

    • Diff -> Exclude
    • Filter -> Extract
      • "This reminds me of Ruby's inject etc. where I don't know what any of the methods actually do."
    • ReturnType sticks around
    • InstanceType is the new "whatever this constructs"

Example:

type NonNullable<T> = Exclude<T, null | undefined>

By the way you can do some crazy stuff.

type JsonifiedObject<T extends object> = { [K in keyof T]: Jsonified<T[K]> };
type Jsonified<T> =
    T extends string | number | boolean | null ? T
    : T extends undefined | Function ? undefined
    : T extends { toJSON(): infer R } ? R
    : T extends object ? JsonfifiedObject<T>
    : "wat";

"Recursive" Conditional Types

Start off with the way that await unboxes Promises to their wrapped type.

type Awaited<T> = T extends Promise<infer R> ? R : T;

Problem: await keeps unwrapping until it gets something that isn't then-able.

You kind of want this:

type Awaited<T> = while T extends Promise<infer R> ? R : T;

or this:

type Awaited<T> = T extends Promise<infer R> ? Awaited<R> : T;

More awaited work

What about this?

type Awaited<T> =
    T extends { then(onfulfilled: (value: infer U) => any): any } ? U :
    T extends { then(...args: any[]): any } ? never : T

Then we modify the definition of Promise to something like this:

interface Promise {
    then<TResult1, TResult2>(
        onFulfilled: (value: Awaited<T>) => TResult1,
        onRejected:  (err: any) => TResult2):
            Promise<Awaited<TResult1 | TResult2>>
}

This almost works!
But there's a problem.
Because the type system doesn't know how to relate an arbitrary T to an Awaited<T> (and vice-versa).
Even if we had the "while types"/recursive conditional types, we'd have the same general problem unless we could think of a general way to handle this.

Resolve JSX namespaces from their factories

#18131

  • What is the motivating scenario?
    • Well there should be nothing preventing you from using multiple versions of React most of the time.
  • But we have this problem with Node.
    • But you only have one runtime environment; you can have multiple versions of React at runtime.
  • [[Something about UMD]]
    • What happens when you have multiple versions of UMD globals that come from different packages?
  • Also, we want to make JSX not global given the next issue...
  • Conclusion: Do this, fall back to a global JSX if nothing is available.

Decoupling JSX.Element from JSX expression return types.

#21699

  • Also, using the JSX namespace is currently being used for too many things!
    • JSX expressions don't always return the type specified by JSX.Element.
  • But people are now depending on this.
  • Conclusion: Do this.

Per-file JSX emit

#21218

  • Do we want a comment?
    • It's the way Babel does it; why be different for no reason?
  • Conclusion: do this.

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