镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Unconstrained type parameter has stricter comparability rules than extends unknown #48680

Description

Fine in 4.7 and 4.6

function foo<T extends unknown>() {
    let x = {};
    x as T;
}

Fine in 4.6, fails in 4.7

function foo<T>() {
    let x = {};
    x as T;
}

Activity

  1. weswigham commented on Apr 13, 2022

    @weswigham
    Member

    Weird. I wonder what comparability is doing to make this happen.

  2. DanielRosenwasser commented on Apr 13, 2022

    @DanielRosenwasser
    MemberAuthor

    Probably this #32814

  3. weswigham commented on Apr 27, 2022

    @weswigham
    Member

    So comparability, as a relation, is in a very bad way from a consistency perspective right now.

    Take this, for example:

    enum E { a, b, c }
        
    declare var a: boolean;
    declare var b: number;
    declare var c: string;
    declare var d: void;
    declare var e: E;
    declare var f: { a: string };
    declare var g: any[];
    
    function fn<T>(t: T) {
      var r8a1 = t < a;
      var r8a2 = t < b;
      var r8a3 = t < c;
      var r8a4 = t < d;
      var r8a5 = t < e;
      var r8a6 = t < f;
      var r8a7 = t < g;
      var r8b1 = a < t;
      var r8b2 = b < t;
      var r8b3 = c < t;
      var r8b4 = d < t;
      var r8b5 = e < t;
      var r8b6 = f < t;
      var r8b7 = g < t;
    }

    this is an except from our tests. All of these comparisons are forbidden (because instantiation may make the comparison forbidden, was our stated logic in the relevant issue). However, this

    enum E { a, b, c }
        
    declare var a: boolean;
    declare var b: number;
    declare var c: string;
    declare var d: void;
    declare var e: E;
    declare var f: { a: string };
    declare var g: any[];
    
    function fn<T extends unknown>(t: T) {
      var r8a1 = t < a;
      var r8a2 = t < b;
      var r8a3 = t < c;
      var r8a4 = t < d;
      var r8a5 = t < e;
      var r8a6 = t < f;
      var r8a7 = t < g;
      var r8b1 = a < t;
      var r8b2 = b < t;
      var r8b3 = c < t;
      var r8b4 = d < t;
      var r8b5 = e < t;
      var r8b6 = f < t;
      var r8b7 = g < t;
    }

    is the same but with one small difference - an explicit constraint. This currently issues no errors on any comparison, despite ostensibly being identical. This is, perhaps obviously, terribly inconsistent.

    The request in the OP of this thread, that

    function foo<T>() {
        let x = {};
        x as T;
    }

    be allowed, implies that all of the comparisons I listed above should be allowed. It's certainly doable (and in fact done, implementation on-hand over in #48861). Conversely, if in presenting this inconsistency I've changed your mind and now you think all these comparisons should be forbidden, we need to add a lot of errors to constrained type parameters in comparability (which is going to be much more breaking)!

  4. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions