Skip to content

Design Meeting Notes, 5/27/2016 #8908

Closed
@DanielRosenwasser

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.
  • In a constructor can you have a public const?
    • We could say public readonly does that?
      • That's conflating the idea.
      • "It's uninteresting" and doesn't come up in practice
  • 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 SyntaxKind in the compiler?

      • Each node would define its own specific discriminator in its kind field.

        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 Node is 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 SyntaxKind equivalent 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 AllColors example, 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.
  • 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.

Metadata

Assignees

No one assigned

    Labels

    Design NotesNotes from our design meetings

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions