Skip to content

Design Meeting Notes, 12/8/2017 #20724

Closed
Closed
@DanielRosenwasser

Description

@DanielRosenwasser

in operators as a type guard

interface Foo {
    abc: number;
}

interface Bar {
    def: string;
}

declare let x: Foo | Bar;

if ("abc" in x) {
    x // Foo
}
else {
    x // Bar
}
  • Since types are open, in the true branch/then branch of the if, it"s not appropriate to say that the x couldn't be a Bar.
    • But we already have this behavior for property access expressions, and most of the time these things are intent-based.
  • Introduces a break to RxJS
  • Conclusion
    • 👍
    • Document that it's a breaking change.

The override keyword

#2000
#13217

  • Without flag, feature is not extremely useful.
  • What about .d.ts files?
    • Would users need overrride
  • Allow users to use override when flag is off.
  • With a flag, it's an error to not use override.
  • Would it go in --strict?
    • Not certain if it feels appropriate.
  • Generally, team feels ambivalent about whether the feature pays for its own complexity.
  • Marked as Accepting PRs last year.
    • Need to be discuss things more in depth before we decide these things.
  • Conclusion: can't accept at this time, would like to think more about annotations after decorators reach stage 3.

Conditional Types

#12424

  • New type operator: T extends U ? X : Y

    • Breaks T does to its union constituents (or T itself if not a union), checks if each of those types is assignable to U.
      • When assignable, you get X, otherwise Y.
    • If T is not known, the type remains unevaluated.
    • Have been back and forth as to whether if T is a union, this distributes over the union.
      • In general, distributing over Tseems to make the most sense.
  • Can make some handy types!

    type Diff<T, U> = T extends U ? never : T;
    
    type TypeName<T> = 
        T extends string ? "string" :
        T extends number ? "number" :
        T extends boolean ? "boolean" :
        T extends undefined ? "undefined" :
        T extends Function ? "function" :
        T extends string ? "string" :
        "object";
    
    type NonNullable<T> = Diff<T, null | undefined>;
    
    type DeepReadonly<T> = T extends object ?
        { readonly [P in keyof T]: DeepReadonly<T[P]> } :
        T;
    
    // Type: "a" | "d"
    type T0 = Diff<"a" | "b" | "c" | "d", "b" | "c">;
    
    // Type: "string" | "function"
    type T1 = TypeName<string | (() => void)>;
    
    // Type: string | number
    type T2 = Diff<string | number | (() => void), Function>;
    
    
    function f1<T>(x: T, y: NonNullable<T>) {
        x = y;
        y = x;
    }
  • How do these interact with any and never?

    • any gives both branches of the conditional.
    • never gives never.
  • Question: Should T extends U be a separate type operator from X ? Y : Z?

  • Should we have && operators as well?`

  • If we did that, it introduces some more syntactical ambiguity.

    • Currently we deal with this by saying "the ambiguities are rare for any useful code.
    • But f<T && U>(5), while a strange way to write f < T && U > 5, feels odd.
    • f<T && U>
  • What about inference for a given branch?

    • A new infer operator?
    • Maybe something like type ReturnTypeOf<T> = from T infer R in (...args: any[]) => R: R
      • Note: would need a constraint on T like (...args: any[]) => R.
    • Then could deconstruct types anywhere?
  • Why did we move away from thinking about match types?

    • Kind of a "Swiss army knife" that does many things.
    • Has curlies which can confuse folks that might think it ends up being an object type.
    • Evaluation order might not be totally obvious to users, whereas conditionals are more explicit about order.
  • Does this give you the awaited type?

    • No.
      • Why not?
        • Evaluation of type aliases is eager, making them lazy would be difficult.
        • But if the type acted on isn't concrete, aren't we deferring evaluation anyway?
        • Maybe it does.

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