Skip to content

Why is type assignability for any and enum so permissive? #22464

Closed

Description

@bcherny

Keywords: any, null, undefined, enum, assign, assignable, assignability, permissive, strict

From the spec:

S is assignable to a type T, and T is assignable from S, if S has no excess properties with respect to T (3.11.5) and one of the following is true:

  • S and T are identical types.
  • S or T is the Any type.
  • S is the Undefined type.
  • S is the Null type and T is not the Undefined type.
  • S or T is an enum type and the other is the primitive type Number.

Why is:

  • S assignable to T, if S is any and T is not any?
  • S assignable to T, if S is a number and T is an enum? Because enum <: number, T should be assignable to S, but why is the reverse true? And why is this not the case for string enums?
  • S assignable to T, if S is undefined? (this was a Playground bug where strictNullChecks wasn't actually applied)
  • S assignable to T, if S is null and T is not undefined?

Have you guys considered a flag to opt out of some or all of these behaviors? Or are there real uses cases for them besides interop with untyped JS (or TS in non-strict mode)? I read through the spec and searched issues, but had trouble finding a discussion of why TS made these design decisions.

Activity

  1. changed the title [-]Why is type assignability with null/undefined so permissive?[/-] [+]Why is type assignability for any and enum so permissive?[/+] on Mar 10, 2018
  2. RyanCavanaugh commented on Mar 11, 2018

    @RyanCavanaugh
    Member

    S assignable to T, if S is any and T is not any?

    We think const v: T = <any>(expr); should not be an error regardless of T or the type of expr. There is always a more-safe type assertion available; someone changing an expression's type to any should be a 100% Get-out-of-jail-free card.

    "But not all anys come from casts!" you say... Right. noImplicitAny is designed to prevent any from appearing in places where you (or someone else) didn't say something was any via explicitly writing that spelling of the type in some place or another.

    There's still the issue of any appearing in lib.d.ts definitions. I think there's a market for a stricter lib.d.ts that puts unknown in place of all anys, but intrinsically changing the definition of any to something else isn't something we think is a productive route.

    S assignable to T, if S is a number and T is an enum?

    Because there's a bit of a paradox presented by the bitwise operators. See #17734, #21546, #11559, #15591 and other issues on this; it's been brought up a few times.

    Have you guys considered a flag

    Most weeks we review about a dozen suggestions for new flags, and we've been doing that for about five years now, so... yes 😉

  3. bcherny commented on Mar 11, 2018

    @bcherny
    Author

    This makes complete sense. Thanks for the quick and detailed response :)

  4. locked and limited conversation to collaborators on Jul 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions