Description
Typed call
/bind
/apply
-
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 usingFunction
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
andNewableFunction
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
orConstructorFunction
might conflict. - We should check BigTSQuery.
- We were afraid that
-
this
is often a little bit funky though withbind
.- Methods in classes have a strongly-typed
this
, but they don't have an implicitthis
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.
- Maybe method syntax could hint that functions use
- We also saw a speed drop as a result of this - effectively, every type becomes generic if it uses method syntax.
- However, it ends up being a big break for interfaces where it's not clear if a given member uses
- Methods in classes have a strongly-typed
-
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
).
- We usually see only
-
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
boolean
now becomes 4 different types- 2 "fresh" Boolean types (fresh
true
and freshfalse
) - 2 regular Boolean types (regular
true
and regularfalse
)
- 2 "fresh" Boolean types (fresh
- Means
readonly
declarations propagatereadonly 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
- 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.