Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Design Meeting Notes, 1/11/2019 #29382

Closed
DanielRosenwasser opened this issue Jan 11, 2019 · 5 comments
Closed

Design Meeting Notes, 1/11/2019 #29382

DanielRosenwasser opened this issue Jan 11, 2019 · 5 comments
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

Readonly generalizations

  • We've had a smattering of issues that relate to readonly.
  • Also, we have a Readonly<T> today.
    • We made changes so that homomorphic mapped types (like Partial<T>) work on tuples
    • But there's no readonly modifier for tuple properties
    • And Readonly doesn't specially treat arrays.
  • Proposing so that
    • type system could make readonly slots in tuples
    • transforms arrays to produce ReadonlyArray.
  • Could this help make Array.isArray work correctly for ReadonlyArrays?
    • Maybe.
  • There's on little nit to it
    • The fact that Array is not assignable to ReadonlyArray, but a T is assignable to a Readonly<T>.
    • This is not the "end of the world".
  • Concern: I don't like this because introducing what appears to be a minor inconsistency can have larger downstream effects.

readonly expression operator

  • People keep running into issues where things widen because of mutability, and it bugs the hell out of them.
  • Ideas:
    • if contextually typed by something that's readonly, you should keep around readonliness
      • "You mean Readonly<T>, or just something with readonly properties?"
  • Are we concerned with adding something to the expression space? Could we just have a readonly keyword that you contextual type, or using as readonly or as const?
    • You don't always have a good contextual space.
    • Definitely a concern about introducing new syntax, but trailing syntax is hard to read.
    • <const>[1, 2, 3]
      • Gross.
    • const might be a better keyword because readonly is only a "view of the world" guarantee; you can't mutate, but someone else might.

Negated types

  • @bterlson: I'm so excited for this

  • @DanielRosenwasser: I feel a bit more negative about them.

  • @weswigham: many of my bugs correspond to people trying to express things with strange conditional types.

    • What people often want is to remove things from the domain.
  • @rbuckton: Can I make a not-not joke?

  • Type relationships

    • not is related contravariantly on its contained type.
      • not Tnot U if UT
    • Snot T if S & T = never.
    • Deferred (i.e. non-simplified) negated types never imply any relation with other types (i.e. not TU).
  • Interesting topics

    • Interplay with narrowing
      • When you narrow out number from a generic type T, should we intersect with not number? (i.e. should you get T & not number)?
      • Could we replace conditional types in Use lib conditional types for type facts if possible #22348 with negated types? They would compose.
        • Sort of, except for the fake mechanism for tagging types.
        • We've let people abuse intersection types with vacuous domains.
        • Okay, imagine this
          • Stringy<T> = T & string
          • NonNullable<T> = T & not null & not undefined
          • Truthy<T> = T & not (0 | "" | false | undefined | null)
        • With let x: { a: number } | string, narrowing with typeof x === "string" you'd end up with string & { a: number }.
        • What if you had a way to say that some of these object types never can overlap with another primitive.
    • Interplay with mapped types?

Out of time

@DanielRosenwasser DanielRosenwasser added the Design Notes Notes from our design meetings label Jan 11, 2019
@Kingwl
Copy link
Contributor

Kingwl commented Jan 14, 2019

Interested about Negated types🤩

@JakeTunaley
Copy link

Really dumb edge case for negated types:

type FiniteNumber = 0
    | 2.225073858507202E-308
    | 2.2250738585072024E-308
    | 2.225073858507203E-308;
    // etc. for every single finite double-precision floating point number, + and -

type NonFiniteNumber = (not FiniteNumber) & number;

function foo (x: NonFiniteNumber | string, y: NonFiniteNumber) {
    if (x === y) {
        // TS thinks that x is a NonFiniteNumber 
        // At runtime, x is either +Infinity or -Infinity, but not NaN
    }
    else {
        // TS thinks that x is a string
        // At runtime, x could be NaN
    }
}

This is because NaN === NaN evaluates to false at runtime, but the type-checker doesn't have special handing for that case (see #15135).

The type-checker will probably run out of memory if anyone actually tries to do this (spoiler: don't try to do this), but it's interesting to know that this is theoretically possible.

@mpawelski
Copy link

mpawelski commented Jan 16, 2019

It would be great if we would get negated type and they would work when narrowing to truthy string or number primitives (probably with another strict flag). It would be yet another great Typescript feature to find bugs in your code 😍

function fun1(num1? : number){
    if(num1){     //ups... should probably be "if(typeof num1 == 'number'){"  
        // Hypothetical compiler error: "Argument of type 'number & not 0' is not assignable to parameter of type 'number'"" or "Argument of type 'Truthy<number>' is not assignable to parameter of type 'number'""
        fun2(num1); 
    }    
}

function fun2(num2: number){
    //do sth with num2
}

@weswigham
Copy link
Member

A number & not 0 is assignable to number - it's a subset of all numbers just like 0 | 1 is. So that wouldn't quite be able to work like that.

@mpawelski
Copy link

ah, of course you're right. I just had this kind of bug recently and got overexcited when I read about negated types 😆

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Notes Notes from our design meetings
Projects
None yet
Development

No branches or pull requests

5 participants