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, 11/2/2018 #28326

Closed
DanielRosenwasser opened this issue Nov 3, 2018 · 0 comments
Closed

Design Meeting Notes, 11/2/2018 #28326

DanielRosenwasser opened this issue Nov 3, 2018 · 0 comments
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Nov 3, 2018

Generic object spread and spread types (continued)

#10727

#21316 (comment)

#28234

  • Back in Add spread/rest higher-order types operator #10727, we speculated that we could have a new kind of type to describe the behavior of spread on generic types.

  • Seemed pretty complicated to come up with a new rules on higher order spread types so we waited on it.

  • Now that our type system has become pretty rich, we started wondering whether we could start to describe spread types in terms of conditional types and mapped types.

  • We can kind of do that, but there are certain caveats: our spread functionality tries to guess the "right" behavior to reflect the runtime.

  • We don't copy methods, we avoid set-only accessors, whatever.

  • Now if we want to do this in a higher-order sense (i.e. on generics), you need a way to select the keys that spread would actually copy those over.

  • So we thought about an own operator, but then you get into some unintuitive cases. For example, you'd think that for the following:

    function foo<T>(obj1: T, obj2: T) {
        return { ...obj1, ...obj2 };
    }

    you'd get something assignable to a T. But no, instead you'd get something like a Spread<Own<T>, Own<T>> - which is not a T, and is not even an Own<T> without some extra work. So this is not great.

  • Up until now, Object.assign just returned intersections.

    • But spreads have almost identical semantics to Object.assign!
    • While it's not correct to return intersections, by and large it's been good enough.
    • So what we do now is that when you have a "zero-order" type (i.e. a non-generic type), we just do what we do today by constructing a new object type; but if you have a generic type, we'll stop and intersect with the current run of spreads.
    • So ...{ x: 100}, ...{ y: "hello" }, ...z where z has type T is { x: number, y: string } & T.

Generic object rest

  • The natural question arises: what about object rest.

  • With Generic object rest variables and parameters #28312, if obj has type T extends { foo: string }, for the following code:

    function f<T extends { foo: string }>(obj: T) {
        let { foo, ...rest } = obj;
        return rest;
    }

    now f returns the type Pick<T, Exclude<keyof T, "foo">>.

  • There was some work that needed to be done with symbols.

    • Wait, symbols aren't enumerable.
    • Does that matter?
    • [[Discussion]]
  • What about the higher order components which are one of the most in-demand use-cases here?

    • Doesn't seem to "work" right

      function excludeTag<
        T extends { tag: string } & U,
        U extends>(
            obj: T) {
                let { foo, ...rest } = obj;
                let blah: U = rest; // error!
            }
  • People might try to use Pick<T, Exclude<keyof T, keyof U>> and it still won't work.

  • Sounds like we need subtraction types!

    • Even though we kind of sort of have them with Exclude.
  • [[Discussion about subtraction types and negated types]]

Partial Type Argument Inference (revisited)

#26349

  • We put out Implement partial type argument inference using the _ sigil #26349 back in August
  • ~6 weeks ago when we last talked about partial type argument inference, we decided not to do anything since we couldn't pick a sigil.
  • Recently Flow implemented the feature and picked the _ character.
  • This is the second-most voted PR on our repo.
  • Seems like there are legitimate use-cases and C# is looking at this; so what's the sigil?
  • Problem with _ is that it's a legitimate use-case
    • BigTSQuery says that there are a couple of uses of _ but explicit type arguments are rare; so contextually reserving it is definitely overkill.
  • Conclusion:

Structurally identical-looking Derived<T> not assignable to Base<T>

#27984

  • We fixed the specific issue, but there are other issues here.

Built-in base configs

#28147

  • Do we want to ship any default configs ourselves.
    • We can ship a set of defaults for well-known workloads (e.g. mixed JS & TS)
  • But your defaults for Babel aren't related to defaults for strictness.
    • So now you need multiple inheritance to combine multiple tsconfigs!?
  • Lots of potential to break.
  • Scaffolding tools already do it all for you anyway.
  • Not clear if it's any more discoverable than the options themselves.
@DanielRosenwasser DanielRosenwasser added the Design Notes Notes from our design meetings label Nov 3, 2018
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

1 participant