Skip to content

Design Meeting Notes, 10/13/2017 #19169

Closed
@DanielRosenwasser

Description

@DanielRosenwasser

Immutability

  • No concrete ideas yet, but here's the background.
  • Many users prefer to program in a very immutable style.
  • If you think about the differences between C# and F#, one of the the things that makes functional programming easier in the latter is immutability by default.
  • But JavaScript doesn't have a library that's amenable to using immutable data structures.
  • So what might the world look like here?
    • Perhaps some way to declare an immutable type is mutable?
    • Perhaps a way to say all fields declared in a type are immutable by default, mutable as an opt-in.
    • But even that's not enough for us - we use a "lazy initialization" pattern where after creation we set the value of a field exactly once.
  • What about something that differentiates the API layer versus within the compilation itself?
    • Depends what's considered your code and what's considered external code in some cases, and we don't have a way of indicating what's part of the API.
    • [[Now we're derailing into how you expose your public API surface]]
      • Then should we have opaque types?
        • Well you can sort of do it today.
      • The idea of immutability has some of the benefits of and is related to generally restricting access to the internals of your programs.

Experimental Stage 1/2 Proposals

  • If you use decorators today, you get a warning that decorators are experimental.
    • But many users are not aware that their decorators are experimental because they start off with a tsconfig that already turns --experimentalDecorators on!
  • Generally we only take stage 3 features now.
  • Idea
    • Don't do anything without an --experimentalStage1Or2 flag (bikeshed on name later)
    • Give a warning all the time which you cannot turn off.
  • The thing is, nobody uses these features to experiment with. They're putting this code into production.
    • So now you're dangling this feature under people's noses but giving a warning that people will become numb to.
  • Conclusion: we can put branches on GitHub, but we don't want to put people in difficult upgrade paths.

Match types

Still in prototyping phase.

type X<T> = match (T) {
    number: "a",
    string: "b",
    else: "c"
}

type A = X<number>;         // has type `"a"`       - matches with `number`
type B = X<1 | "hello">;    // has type `"a" | "b"` - `"hello"` and `1` are subtypes of `number` and `string`
type C = X<object>          // has type `"c"`       - fell into the `else` branch

One concern (a.k.a. a feature!) is that this allows us to branch.

type Conditional<C, T, F> = match (C) {
    true: T,
    false: F,
}

This all arose from discussion around the awaited type PR where many people requested a more general solution.
With awaited, we'd have functionality like so:

type X = awaited Promise<Promise<number>>;
// X =  number

We need a way to introduce type parameters to emulate this

type Awaited<T> = match (T) {
    PromiseLike<infer U>: Awaited<U>,
    else: T,
}

We would need to add some recursion checks like we do in other resolution algorithms.

Main question: what about the higher order type relationships? It's effectively like trying to relate two switch statements.

Metadata

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