Skip to content

Date.getMonth could return a union of all possible values #36401

@nikeee

Description

@nikeee

Search Terms

Suggestion

According to the MDN docs, Date.getMonth() always returns a number between 0 and 11 (inclusive):

An integer number, between 0 and 11, representing the month in the given date according to local time. 0 corresponds to January, 1 to February, and so on.

Currently, the lib.d.ts definition states that this function returns number.

So I suggest du change the definition of getMonth() from:

TypeScript/lib/lib.es5.d.ts

Lines 750 to 751 in 91ffa1c

/** Gets the month, using local time. */
getMonth(): number;

...to something like:

interface Date {
    // ...
    /** Gets the month, using local time. */
    getMonth(): 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11; // (or using a type definition for this union)
    // ...
}

Use Cases

This would be beneficial if user code contains something like if (date.getMonth() == 12). The compiler can then infer that the entire if branch is dead code.
Also, it serves as a quick documentation to let the user know that the return value is in fact a 0-based (not 1-based) month. The number of months in a year is also unlikely to change as well as the base (0/1) of the month index that this function returns.

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code <-- I'm not sure about that. It should not be breaking, since 0 | ... | 11 is a subset of number.
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

Remarks

This could likewise be done for getUTCMonth().

There are other methods like getMinutes() and getSeconds(). As they return something in the range of 0 to 60, could also be modeled using a union. However, I think that a large union like this may be considered differently.

Also, there are setters for these values (like setMonth()). Changing the parameter of this function to take a 0 | ... | 11 would actually be a breaking change. It would not reflect the runtime behaviour. setMonth(15) would be a valid statement that will increment the year by 1 and the months by 3. So the setters should be kept as using number.

If this is up for grabs, I'd take this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions