Skip to content

Design Meeting Notes, 3/2/2018 #22304

@DanielRosenwasser

Description

@DanielRosenwasser

More Special Declaration Types in JS

#21974

In 2.7, we started treating variables initialized with empty object literals as namespaces in JS files.

var foo = {};
foo.x = 10
foo.y = 20;

Now you can omit the var

app = {};
app.C = function() { 
    // ...
}

Also allows IIFEs to be namespaces.

var C = (function () {
    function C(n) {
        this.p = n;
    }
    return C;
})();

[[Daniel: I'm going to stop here because you can just read the PR writeup.]]

  • We need to put these together in one document.
  • Why do we do this in JavaScript and not in TypeScript?
    • We're supposed to be a superset.
    • What about declaration emit?
      • Would we serialize using the TS-specific syntax?
    • Should we only recognize this with var declarations as opposed to just consts?
      • Can always re-assign to a var.
  • It is currently still awkward to transition from a .js file to a .ts file.
    • You switch to .ts and you become temporarily untyped even if you want
    • What about a mode that enables these constructs in .ts?
    • What about if allowJs just permitted this?
      • How do you disable the behavior though?
        • When do you want to disable it?
          • When you want to start writing super-strict .ts in existing JS code.
    • "I'm worried about having too many flags"
      • [[laughter]]
  • What about initializing fields in a class?
    • TypeScript requires fields to be declared up-front
    • How do you prevent misspelled properties?
  • Conclusion: we will think harder!

The unknown type

#10715

  • Prototyped it as a new primitive type.
  • Doesn't have to be a new primitive type.
    • In non-strict mode, everything is assignable to {} except for void.
    • In strictNullChecks, you get a problem because you have to write {} | null | undefined; it's annoying.
    • Can just write an alias!
      • That way you can still get narrowing; check != null and then you'll be able to call toString() on it.
  • Problem: If we put this in lib.d.ts, you can run with skipLibCheck and TypeScript won't always print that out because it won't have seen the alias.
    • We could fix this in strictNullChecks mode by forcing the checker to resolve this.
    • But then in non-strictNullChecks mode,
  • What about failed type argument inference?
    • Could default to unknown instead of {}?
    • But not clear you get a lot of value from that.
    • Could also not do anything.
    • Problem: implies you'd need to change the constraint; implementations of generic functions currently make the assumption that type parameters will not be null or undefined (constraint is implicitly {}).
  • We want it highlighted as a keyword though...
    • So should it be an alias?
  • Open questions
    • Does x > 0 imply narrowing?
      • No.
    • if (x) narrows to {}?
      • Yes.
    • if (!x) narrows to {} | null | undefined?
      • Yes.
      • Currently no?
      • @chancancode reported this and we said "ehhhh"
    • What does { [s: string]: unknown } mean?
      • Problems with dictionaries becoming assignable to anything.
    • What's the type of unknown | T?
      • Question becomes "should we collapse unions containing {}?
        • Probably yes?
      • But then you lose the contextual type in some cases, which would break a bunch of React code.
        • We need to see what people are doing on DefinitelyTyped and see what the intent is there.
          • Should write a TSLint rule to track them down.
    • What's the type of s!?
      • {}
      • (as opposed to object | string | number | boolean).

Distribute keyof on intersections

#22300

This now works as expected!

type X<A, B> = Record<A, object> & Record<B, object>

// keyof A | keyof B
type Y<A, B> = keyof X<A, B>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design NotesNotes from our design meetings

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions