Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Design Meeting Notes, 12/8/2017 #20724

Closed
DanielRosenwasser opened this issue Dec 15, 2017 · 0 comments
Closed

Design Meeting Notes, 12/8/2017 #20724

DanielRosenwasser opened this issue Dec 15, 2017 · 0 comments
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Dec 15, 2017

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.
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
Design Notes Notes from our design meetings
Projects
None yet
Development

No branches or pull requests

1 participant