Skip to content

Design Meeting Notes for 3/11/2016 #7488

@DanielRosenwasser

Description

@DanielRosenwasser

Non-nullable types (#7140)

Question marks on types

Let's start the bike-shedding! What does T? mean?

function foo(x?: string) {
    // x: string | undefined
}

function foo(x: string?) {
    // ?????
}

function foo(x?: string?) {
    // x: string | undefined | ?????
}
  • @ahejlsberg: It's hard to imagine a world where T? means only T | null or only T | undefined.
  • There is a school of thought that says "neither - this just doesn't need to exist".
    • Just ship two type aliases for T | null and T | undefined in lib.d.ts
    • We can sort of see that. It's not crazy.
    • We can't satisfy everyone - we're going to piss someone off.
    • But if we ship this without a ? type modifier, it's the first thing we're going to hear, and we're going to hear it for the rest of our lives.
  • What's crazy about T | null?
    • You have an optional accessor that returns number? | undefined.
      • You end up with these awkward, funny-looking types.
    • Lack of symmetry between optional members and nullish types.
      • Becomes like the const modifier in C++.
      • Nobody understands where the heck to put const (before *, after *, at the end of a signature), and the differences are hard for people to grasp.
        • We understand it, but our users will get tripped up a lot.
    • People will definitely be confused about which to do.
      • Users on GitHub did not seem to be concerned with it - they understood very well.
        • Confirmation bias - these are people who are interested in language design to begin with.
  • Too many people are doing null to ignore that scenario.
    • Ultimately the question becomes is this disjoint or does it combine with the "other" use of ? on optional parameters/properties.
  • @RyanCavanaugh: Extremely against T? meaning T | null | undefined because it muddies waters - So if we can't come to a conclusion, I think we should hold off on it.
  • We want to lead people to a pit of success, and we can't repeat the problem we have with modules.
  • Only consistency in discussion on thread is that there is no consistency.
  • We don't feel confident that we can do the "right" thing here out of the gate.
  • If people go out and fix type definitions and inappropriately use ?, then you've made the ecosystem worse - we need to wary of this possibility.
  • @Aleksey-Bykov you get a ⭐
  • Consensus: come back to this, since this is not a blocker for non-nullable types anyway.
    • Also, look into supplying type aliases in lib.d.ts.

Optional members on new members

  • Considering adding question marks on other members ([Request for feedback] Nullable types, null and undefined #7426 (comment))
    • On local variable names (e.g. let x?: number).
    • On property declarations in classes (e.g. class Foo { x?: number }).
    • On call signatures (e.g. function val(x?: string)?: number).
    • On index signatures (e.g. [x: string]?: Entity).
  • We said it wasn't necessary because classes always have undefined by default, but non-nullable types make the world quite different.
  • Variables are more of a questionable (pun intended) case - not entirely certain.
    • It seems like this would actually give you a case to say that your variable can be undefined and reflects that in the type.
    • Can we use that to model the dual of this on ? in types?
      • Let's not go down that rabbit-hole.
  • Call signatures would have an awkward syntax.
  • Consensus: do it for properties, keep the rest this in mind, but come back to it.

Control-flow based type checking

  • We're going to need to do it.
  • We think we can do it with no significant perf hit.
  • Get perfect definite assignment errors.
  • Type guards should work perfectly.
  • We'll keep people posted.

UMD module support (#7264)

  • Idea with UMD modules is you write a declaration file.
  • In that same file, you write export as namespace Foo where Foo is some arbitrary identifier.
  • In a module, only if you use a /// <reference path="..." />, is Foo visible.
  • In a script context, Foo is always visible if the .d.ts is in the compilation context.
    • Idea is that you're in a script/"non-module" context.
  • This is the new, better, way to write type definitions that need to be shared between old script-style code and modules.
    • The problem is that you always needed to duplicate your definitions across two different definition files, one which used an export =.
  • Problem: how do you reflect the type of the module itself?
    • Sometimes modules have members that refer to themselves.

    • We're still flexible here!

    • Continue using some value, use export =, and then use an export namespace as Foo.

      interface jQueryStatic {
          foo: jQueryStatic
      }
      
      let jQuery: jQueryStatic;
      export = jQuery;
      export as namespace jQuery;
  • Why does /// <reference path="..." /> affect things? Why not just use a global module augmentation?

Library include directives (#7263)

  • Answer to the question of "How do we easily resolve types for script/global code?"
    • Need to avoid situations where users have duplicate definitions due to "global code" being treated as conflicting even though they might refer to the same entities.
  • Syntax: /// <reference library="jquery" />
  • What is the order of resolution for declaration files?
    • Take /// <reference library="jquery" />.
    • Start from current module location.
    • Look for files walking up the spine of directories. For each directory:
      1. If you see a file named jquery.d.ts, use that.
      2. If you see a directory named typings, look in there.
      3. If you see a directory named node_modules
        1. Try to resolve in node_modules/jquery/package.json or use the node_modules/jquery/index.d.ts.
        2. Try to resolve in node_modules/jquery/package.json or use the node_modules/@types/jquery/index.d.ts (or something similar).
  • Meeting cut short - may be more to the algorithm.

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