- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.1k
Description
Expanded Inference (Open & Expando Style Types)
There's lots of code out there that has no type annotations at all, no initializers, starts out as an empty object.
That's mostly existing JavaScript code.
Anders has been working on using CFA to track types completely in certain situations.
function foo() {
    let x;
    if (!!true) {
        x = 1;
    }
    else {
        x = "hello";
    }
    x; // has type 'number | string'
}This works pretty well if we have an accurate picture of the control flow graph; however, you can't model this that well if these variables are captured in another function.
For instance:
function foo() {
    let x;
    if (!!true) {
        x = 1;
    }
    else {
        x = "hello";
    }
    x; // has type 'number | string'
    function captor() {
        x; // implicitly has type 'any'.
    }
}That means that 'any' has a much more limited scope of being implicitly introduced.
This makes Salsa way more powerful!
Expando Objects
Expando is a (somewhat documented) feature and pattern in JS where you can continue tacking properties on to objects after their creation.
In certain sites, we can decide that an object is meant to be created as an "expando" type.
For instance, how useful is the type {} on its own?
The answer is "not very useful" (unless you're just using it for object identity), so we can build up the type as you assign properties to that object.
let x = {};      // after this, 'x' has type '{}'
x.a = 1;         // after this, 'x' has type '{ a: number }'
x.b = {};        // after this, 'x' has type '{ a: number; b: {} }'
x.b.y = "hello"; // after this, 'x' has type '{ a: number; b: { y: string} }'
x;               // 'x' has type '{ a: number; b: { y: string} }' here.Every occurrence of x above has its own type.
Side note: This is widely used and the VS JS language service lost out a lot on this in switching to Salsa.
Both TypeScript and the Salsa JS LS would get this for free.
Q: Does this work for element access expressions?
A: No, haven't worked that far yet.
Q: Could we do this sort of thing for this in constructors?
A: Potentially very bad experience - what happens if users set a value to undefined? It's worth experimenting with though.
Q: Does this work for aliasing?
A: No, alias tracking would get pretty messy.
Expanded Array Element Inference
What about arrays?
This hasn't been implemented yet, but we have some ideas here.
Look for locations in which the array is added to (indexing, push, unshift).
let x = [];
x[0] = 4;        // 'x' has type 'number[]'
x.push("hello"); // 'x' has type '(number | string)[]'Changes of Inference
General discussion about why an initializer is different from a deferred initialization.
Questions about inferring literal types, concerns about breaking changes.
tsconfig.json Inheritance
- "Is there a reason why we wouldn't?"
- "No."
- "Then why don't we do it?"
- Open questions (duh!).
Merge or Overwrite?
Overwrite.
Multiple or Single Inheritance
Everyone: "SINGLE."
That was easy.
Object Literal Rest & Spread
let x = { a: 0, b: "hi" };
let y = { a: true};
// This is equivalent to 'Object.assign({}, x, {a: 2 }, y)'
let z = {
    ...x,
    a: 2,
    ...y
};
// Ideally, has type '{ a: boolean, b: string }'
z;Problem: Object.assign gives an intersection of its types.
Easy to do when types aren't generic.
But what if they are?
// What is the return type here?
function merge<T, U>(o: T, ext: U) {
    return {...o, ...ext};
}Idea: new type operator like {...T, ...U}
Q: What about if U has an optional property that exists in T?
A: Probably union the types of each property.
Enumerable & Own Properties
class C {
    a = 0;
    b = "stuff";
    method() {
    }
}
let c = new C();
let d = { ...c };Problem is that d doesn't get method because it's not enumerable or an own-property.
We'd need a new modifier in type members.
"Optionalization"
function setState<T>(o: T, ext: optional T) {
    return {...o, ...ext};
}There are often scenarios where you want to create a type with optional portions.
Not a lot of time to discuss this today.