- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.1k
Description
Narrowing within Function Expressions
const Modifiers on Function Parameters
functin f0() {
    let x = getStringOrNumber();
    if (typeof x === "string") {
        const f = () => x.length; // currently errors
    }
}- We don't make an effort to dive within functions expressions - we don't narrow within them.
- However, when you have a const, you know for sure that you can definitely narrow.
- We're making sure that works.
- Problem is, you can't reflect that behavior with parameters today.
 
- However, when you have a 
- In a constructor can you have a public const?- We could say public readonlydoes that?- That's conflating the idea.
- "It's uninteresting" and doesn't come up in practice
 
 
- We could say 
- What about nested members of a const?- 
i.e. const x = { foo: { bar: number } }; x.foo.bar; 
 
- 
IIFEs
Repro from #8381
(function() {
}())- Look at the PR
Enums & Algebraic Data Types
- 
Simple approach is that you use singleton value types. - 
Currently, these singleton value types are limited to string literal types. type Foo = "up" | "down"; var x: Foo; switch (x) { case "up": // ... break; case "down": // ... break; } 
- 
Gets more interesting with something like: interface Up { kind: "uP"; speed: number; } interface Down { kind: "down"; fatal: boolean; } var x: Up | Down; switch (x.kind) { case "up": x.speed; break; case "down": x.fatal; break; } - Forgive the terrible example.
 
- 
These need not be string literals - they could be numbers, enums. 
- 
Wouldn't it be nice if we could do this sort of thing with SyntaxKindin the compiler?- 
Each node would define its own specific discriminator in its kindfield.interface Node { kind: SyntaxKind; } interface PropertyAccess { kind: SyntaxKind.PropertyAccess; } 
- 
Problematically, you couldn't quite do this with the OO-style property inheritance we get (open-ended in OOP, close-ended in FP). 
- 
Ideally, you could do exhaustiveness checking with this, but Nodeis open-ended right now.- 
So you'd do something like this: interface NodeBase { kind: SyntaxKind; } interface PropertyAccess { kind: SyntaxKind.PropertyAccess; } interface CallExpression { kind: SyntaxKind.CallExpression; } type Node = PropertyAccess | CallExpression // | ... 
- 
What would the type of a Node's kind be now?- 
SyntaxKind.ProperyAccess | SyntaxKind.CallExpression | ....
- 
Is SyntaxKindequivalent to that union type?
- 
Not necessarily! That can be confusing! 
- 
So you'd have to do something like this: const enum Color { Red, Green, Blue } type AllColors = Color.Red | Color.Green | Color.Blue; 
 
- 
 
- 
 
- 
 
- 
- 
So to avoid the AllColorsexample, you could imagine that we'd have a new kind of enum:union enum Color { Red, // 0 Green, // 1 Blue // 2 } - Couldn't use flags in this example.
 
- 
TC39 convo on enums had symbols in mind. - Issues with that.
- Need to be able to serialize that in an error message.
 
 
- Issues with that.
- 
DR: I think we could do ADT-style stuff without needing enum types yet. - AH: Yes, and strings are fine, but you really can't do that with numbers.
- DR: But ADTS are moe general.
- AH: But string/number discriminators are the real value of this feature.
- DR: Agreed.
 
- 
DR: Problem is that the base-type/intermediate-types/union-type pattern is cumbersome - you've fixed the enum type, done nothing there.