this-types for functions (#6739)
- Defines ability to define type of
this for the scope of a function.
- If you're in a class,
this is assumed to have the type of the class itself.
- You can still override this by giving an explicit type to
this.
Strict this checks
- Problem: cognitive burden by creating a distinction between types of methods and properties with function types.
- Looked at performance against
master.
- Lots of variance.

- But does look like there is a consistent perf hit.
- <10%, >5%.
- Incompatible with old code in some cases.
- Need to update
.d.ts files.
- Huge undertaking.
- Already tons of stuff for
- Options in light of this.
- We can take neither.
- We can take the backwards-compatible stuff, forget the strict
this checking.
- We can take both, and give people a heads up that there's going to be a perf hit for strict
this checking.
- Conclusion: hold off on strict-
this.
No implicit this
- Should we have that?
- Should it be part of
noImplicitAny?
- Well that breaks code.
- You'd need a suppressing flag.
- Nobody likes that, so
noImplicitThis would not be umbrella'd.
Library modularization (#6974)
-
Background: hard to say what environments will have what at runtime.
Our libraries try to be all-encompassing.
The workaround has been to modify lib.d.ts on your own, but nobody wants to do that.
-
Current solution: granular libraries.
-
What about ambient decorators?
-
You have es6.array.d.ts, es6.collection.d.ts, etc.
-
New --lib flag, takes a list of options.
- You can still just specify
es6 as the lib as an aggregate flag (include es6.*.d.ts).
- Also have an
es7.d.ts for all one functions that were added to ES7.
--target toggles the default if --lib isn't specified.
--target es2015 still includes lib.es6.d.ts.
- What about ES2015? ES6 technically doesn't exist.
- Everyone hates the official name.
- We have no choice. ¯_(ツ)_/¯
-
So by default, you get the ES3 lib?
- Sort of. It's more like ES5.5. We haven't split out the ES3/ES5 stuff.
- Why?
- Backwards compatibility.
- So due to back-compat, is DOM always in
lib.d.ts?
- Yes?
- But you can just use
--lib es5 and add from there on.
- To add to that, you make it
--lib es5,dom.
- But we could always add
--lib node.
-
What about granular transformations?
- People want
async/await because Node has it, but as soon as you try to do ES6 emit, you run into problems like Node not supporting destructuring.
- That's the next step.
Conditional compilation stuff
- We're not fully committed to this.
Granularity
- The granularity is great.
- But there are some clear defaults.
- Are there situations where people need all this granularity?
- Can overwhelm users, can become a maintenance headache.
- Let's keep these split up, not commit to them just yet.
Control Flow Analysis For Everything (#2388)
- Background:
- We needed reachability analysis.
- Now we need control flow-based type analysis.
- Now, we've subsumed reachability analysis with our work on control flow-based type analysis.
- We now track all assignments and type-guards.
- Assignments are now considered type-guards themselves as well.
Consider
function countLines(text: string[]) {
let count: number;
for (const line of text) {
if (line.length !== 0) {
count = count + 1;
}
}
return count;
}
-
Our new checks will now yell at you for forgetting to initialize count and not informing us that count could be undefined.
-
Even if you initialize it at the wrong point.
function countLines(text: string[]) {
let count: number;
for (const line of text) {
count = 0; // not good enough - this loop might never execute!
if (line.length !== 0) {
count = count + 1;
}
}
return count;
}
-
We also infer correctly from falling through.
function countLines(text: string[]) {
if (text) {
let count: number = 0;
for (const line of text) {
if (line.length !== 0) {
count = count + 1;
}
}
return count;
}
}
countLines has type number | undefined since you implicitly returned undefined.
Assignments as a new type guard point
declare function getNumberOrString(): number | string;
var x = getNumberOrString(); // has type 'number | string'
if (typeof x === "string") {
x; // has type 'string'
x = 1000; // still okay to assign a 'number'
x; // has type 'number'
}
Shortcomings
Array accesses
Technically we should be introducing undefined from array indexing, but this would be such a massive pain for users that we can't consider this path.
Variable capture in closures
We don't track usage of a variable's use within a function.
function uh_oh() {
return s.slice();
}
var s: string;
uh_oh(); // no error.
Potential for other work
- Could we use this logic for checking for
this before super, etc.?
this-types for functions (#6739)thisfor the scope of a function.thisis assumed to have the type of the class itself.this.Strict
thischecksmaster..d.tsfiles.thischecking.thischecking.this.No implicit
thisnoImplicitAny?noImplicitThiswould not be umbrella'd.Library modularization (#6974)
Background: hard to say what environments will have what at runtime.
Our libraries try to be all-encompassing.
The workaround has been to modify
lib.d.tson your own, but nobody wants to do that.Current solution: granular libraries.
What about ambient decorators?
You have
es6.array.d.ts,es6.collection.d.ts, etc.New
--libflag, takes a list of options.es6as the lib as an aggregate flag (includees6.*.d.ts).es7.d.tsfor all one functions that were added to ES7.--targettoggles the default if--libisn't specified.--target es2015still includeslib.es6.d.ts.So by default, you get the ES3 lib?
lib.d.ts?--lib es5and add from there on.--lib es5,dom.--lib node.What about granular transformations?
async/awaitbecause Node has it, but as soon as you try to do ES6 emit, you run into problems like Node not supporting destructuring.Conditional compilation stuff
Granularity
Control Flow Analysis For Everything (#2388)
Consider
Our new checks will now yell at you for forgetting to initialize
countand not informing us thatcountcould beundefined.Even if you initialize it at the wrong point.
We also infer correctly from falling through.
countLineshas typenumber | undefinedsince you implicitly returnedundefined.Assignments as a new type guard point
Shortcomings
Array accesses
Technically we should be introducing
undefinedfrom array indexing, but this would be such a massive pain for users that we can't consider this path.Variable capture in closures
We don't track usage of a variable's use within a function.
Potential for other work
thisbeforesuper, etc.?