TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

No error on unconstrained type parameter in `>` comparison

Open cakoose opened this issue 3 years ago • 4 comments

Bug Report

🔎 Search Terms

object is possibly undefined 4.8

🕗 Version & Regression Information

  • This changed between versions 4.7.4 and 4.8.2

⏯ Playground Link

TS playground on 4.8.0-beta link.

(The playground doesn't seem to have 4.8.x releases, but I tested on 4.8.0-beta and nightly (4.9.0-dev.XXXXXXX).)

💻 Code

export function min<T>(it: Iterable<T>): T | null {
    let result: T | null = null;
    for (const v of it) {
        if (result === null || result > v) {
            result = v;
        }
    }
    return result;
}
error TS2532: Object is possibly 'undefined'.

        if (result === null || result < v) {
                               ~~~~~~

On that line, hovering over the first result shows T | null. Hovering over the second result shows T & ({} | undefined).

🙁 Actual behavior

I get a type error.

🙂 Expected behavior

No error.

cakoose avatar Sep 02 '22 06:09 cakoose

This is expected behavior in 4.8. See this section in the blog post: https://devblogs.microsoft.com/typescript/announcing-typescript-4-8/#unconstrained-generics-no-longer-assignable-to

You probably want to change your type variable to be constrained to {} by writing T extends {}, or check for undefined.

jakebailey avatar Sep 02 '22 06:09 jakebailey

Ah, interesting! Where's the {} requirement coming from, the comparison?

For example, I'm confused why there's no error here:

function f<T>(a: T, b: T): boolean {
    return a > b;
}

cakoose avatar Sep 02 '22 07:09 cakoose

Honestly, I didn't even notice that the operator you used was >. It does seem weird that the above compiles, yet, this does not.

function f<T>(a: T, b: T): boolean {
    if (a === undefined} {
        return true;
    }

    return a > b;
}

In that it's odd that we allow > and < on an unconstrained type variable like this.

jakebailey avatar Sep 02 '22 17:09 jakebailey

The current behavior is clearly inconsistent. If you can’t use undefined in a greater than or less than check, you shouldn’t be able to use an unconstrained type parameter either.

andrewbranch avatar Sep 02 '22 17:09 andrewbranch

Note that the issue reported here also exists for the +, -, and ~ unary operators. For example:

function foo<T>(x: T) {
    +x;  // Ok
    if (x === undefined) return;
    +x;  // Error
}

With #59437, errors are reported in both cases above.

ahejlsberg avatar Jul 29 '24 01:07 ahejlsberg