-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
Joke of the day
- Anders: "What do you call a fish without an eye?"
- "Fsh!"
Breaking Changes
"use strict" changes for modules (#3676)
- Requested by several people.
- Broke several people.
- New flag
- Yay, new flags!
- Today's flag is...
emitNonStrictModules.- Keeps compliance, but allows people to revert behavior.
- Do we emit
"use strict"for classes?- No.
- We should.
- Should this flag affect that when we make that change?
- Yes, let's give the flag a better name to reflect that.
- Would we be breaking people if we actually did this though?
- Apparently yes.
Defaulting to built-in promises
- We used to use type annotations as a guide to enable a bring-your-own-promise scenario.
- Doesn't match with semantics reflecting original spec.
- Breaks design goals.
- Could we remove the restriction for ES6 (ES7?) and prior?
- Sure?
- Options:
- Keep breaking change
- Undo the change, perform the breaking change when we actually have downlevel
async/await.
- Resolution: undo the change, apply it when we actually allow users to downlevel their
asynccode.
Features (and potential breaking changes)
Specifying this types for functions (#6739)
-
What does the "strict
this" world look like? -
We will check
thisjust as if it was an argument today. -
Consider
class Foo { m() { this.blah(); // ... } blah() { // ... } } let foo: Foo; let e: () => void = foo.m; e();
- That example will crash because
mhas been orphaned from itsFooinstance.
- That example will crash because
-
Strict
this-checking aims to fix this issue. -
thisappears in the parameter list for functions and function types. -
thistypes affect assignability of signatures:type EventA = (this: Element, x: string) => void; type EventB = (this: void, x: string) => void; let a: EventA; let b: EventB; a = b; // Error: 'void' isn't enough for a method needing an 'Element' for 'this'. b = a; // Okay: No problem with getting *more* than you expect.
- Assignability is still bivariant for a
thisparameter
- Assignability is still bivariant for a
-
In strict-
thismode, the following's an error:function foo(s: string) { this.abc; // Error: 'this' is implicitly a 'void'. }
-
Arrow functions will always hold the value of
thisfrom their containing scope. -
Free-standing functions implicitly get a
voidtype forthis. -
Methods in classes implicitly have a
thistype ofthis.- Hopefully this is not very surprising.
- This prevents incorrectly "ripping off the method" (
thisorphaning) from the first example.
-
Static methods have a
thistype oftypeof FoowhereFoois the containing class. -
Does this fix the
bindfunction?- Almost!!
-
Why do we need a flag?
-
It breaks existing code for when your methods have no dependency on
this. -
Occurs several types in the compiler.
-
Problems sprout up between methods signatures and function type literals:
interface Foo { a(): void; b(): void; } interface Bar { a: () => void; b: () => void; }
Foomethods implicitly get athis: thistype, whileBarmethods get athis: voidtype!- We need to be prescriptive and explain to people how to write definitions.
- People are still going to run into such gotchas.
-
-
By default, without the strict-
thisflag, there will be no impliedthistype. -
But we still want contextual typing to work correctly:
addOnClick(function (e) { // 'this' has the 'Element' type. this./*|*/ // | // +-- Members of the 'Element' type. });
-
What about object literals?
-
If the object is contextually typed by
X, methods will get thethistype ofX.var o: X = { x: 10, m() { this // has type 'X' } }
-
An object literal with no contextual type just grabs the type of the object literal:
var o: X = { x: 10, m() { this // has type '{ x: number; m(this: /*typeof o?*/); }}' } }
- Uh-oh, how will the declaration emitter and language-service print the type of
o?
- Uh-oh, how will the declaration emitter and language-service print the type of
-
-
Speaking of surfacing the representation of these types...
interface Foo { bar(); } // What is the type of 'foo'? (this: this) => void? const foo = foo.bar;
-
So are all these very big changes going to need these sorts of flags?
- Are we going to have a "very strict mode"?
-
Do overload
thisparameters need to match?- No.
Unique types/tagged types/opaque types
-
People keep asking for this.
-
Ideas from last time:
unique class C { // ... } unique interface I { // ... } unique type Path = string;
-
The biggest question last time was what the behavior was for the type alias example (i.e.
Path). -
We're thinking that
type Path = string & (unique {});
- We can also do some stuff so that
Pathwill be printed asPath.
- We can also do some stuff so that
-
This approach, combined with intersections, allows you to "compose" on existing types.
-
You can write
Path & Lowercased. -
Unique interfaces are useful for preventing people from forging nodes.
-
What about if a base is unique?
-
Does
uniqueaffect the static side?- Maybe?
- Actually, you get that for free because the constructor function returns a unique type.
- Well almost. But that would require a type assertion anyhow.