Skip to content

Design Meeting Notes, 9/14/2018 #27102

@DanielRosenwasser

Description

@DanielRosenwasser

Typed call/bind/apply

#27028

  • Idea here is that ~4 years ago, someone complained about call/bind/apply not being typed.

  • Didn't want to build it directly into the type.

  • Could have added this into the Function interface, except that a lot of people were using Function as a catch-all for function types, so things were relatively breaky.

  • Now, when we check for the "apparent type" of something (i.e. what members it has), we jump to CallFunction and NewableFunction if something has a call signature or a construct signature.

  • Should we be calling it ConstructableFunction instead? It's more fitting given conventions and

    • We were afraid that ConstructableFunction or ConstructorFunction might conflict.
    • We should check BigTSQuery.
  • this is often a little bit funky though with bind.

    • Methods in classes have a strongly-typed this, but they don't have an implicit this parameter.
    • We had a strictThis PR from a while back.
      • However, it ends up being a big break for interfaces where it's not clear if a given member uses this or not.
        • Maybe method syntax could hint that functions use this, but we can't easily make that assumption now that we're 5 years in.
        • If we could rewind time, we might change this.
      • We also saw a speed drop as a result of this - effectively, every type becomes generic if it uses method syntax.
  • Despite all our expressiveness, we still need an "overload ladder" for bind.

    • We usually see only this being bound, with at most 1 parameter.
    • Currently we have bind taking up to 4 arguments.
    • We also give one special overload for functions with single rest parameters (e.g. (...args: T[]) => any).
  • If you call bind on an arrow function, what happens if you pass the first parameter.

    • It just gets ignored.
  • We did make some changes to inferences for type parameters that occur in co/contravariant positions.

    • Make error reporting a bit better.
declare function invoke<T>(f: (x: T) => T, x: T): T;

declare function bar(s: string): string;

declare const foo: "a";

invoke(bar, foo);

invoke(bar, 100);

Boolean literal freshness

#27042

  • boolean now becomes 4 different types
    • 2 "fresh" Boolean types (fresh true and fresh false)
    • 2 regular Boolean types (regular true and regular false)
  • Means readonly declarations propagate readonly foo = true in .d.ts files.
    • Note that this is actually a breaking change. Now the declaration files may not work in 3.1.
  • Conclusion: Let's do this.

Recursive Types

#14174
#26980

  • The intuition is not possible to form object graphs with circularities unless you defer somehow (either via laziness or state).
  • Really there's no way to know if any arbitrary type will terminate.
  • We can have limited types of recursion in the compiler, but the problem isn't whether or not the type terminates, it's how computationally intensive and memory heavy the resolution is.
  • We have a meta-question: do we want people writing code like this?
    • The motivating scenarios that people have are legitimate, but achieving them with these types is not necessarily going to work well for library consumers.
  • Conclusion: we're not quite ready for this sort of thing.

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