Skip to content

Missing type-check on explicit cast? #9312

Closed

Description

TypeScript Version:

1.8.10

Code

interface Foo {
    foo()
    bar()
}

// does NOT error:

var a = <Foo> {
    foo() {}
    // missing bar() - no error!
}

var b = {
    foo() {}
    // missing bar() - no error!
} as Foo

// errors: (b not assignable to type Foo)

var c: Foo = {
    foo() {}
    // missing bar() - error
}

function d() : Foo {
    return {
        foo() {}
        // missing bar() - error
    }
}

In the two first cases, the shape (and inferred type) of the anonymous object are missing a method and clearly are not assignable to Foo - I was expecting an error message.

I don't fully understand why assignment to a var vs assignment to an explicitly typed var or return-type would behave inconsistently in terms of type-checking.

Didn't it use to be that you had to do something like var a = <Foo> <any> { .. }, e.g. you had to explicitly cast the inferred object type/shape to any before you'd be allowed to do an unsafe type-cast?

Activity

  1. RyanCavanaugh commented on Jun 22, 2016

    @RyanCavanaugh
    Member

    Enforcing the normal direction of assignability as part of a type assertion would be counterproductive (or at least counterintuitive) -- if it were already assignable, you'd never write the cast in the first place!

    The rule is that the expression type and the asserted type must be assignable in one direction or another. This prevents obviously-wrong assertions like <string>window while still allowing correct-looking assertions like <Horse>someAnimal.

    There's another issue somewhere I can't find at the moment that talks about having a type assertion operator that changes the type of an expression without performing the bidirectional check. I can probably dig it up if you're interested.

  2. mindplay-dk commented on Jun 28, 2016

    @mindplay-dk
    Author

    The rule is that the expression type and the asserted type must be assignable in one direction or another

    Ryan Cavanaugh (@RyanCavanaugh) that makes sense for something like <Horse>someAnimal, but probably not so much for an inferred Object as in my first example? Because practically everything is Object in one direction or the other.

    It seems like an exemption might make sense there - because the two first examples are obviously wrong; the inferred type clearly has a shape that is directly incompatible with the type assertion being made, yet they compile without complaint.

    At least a warning or notice should be appropriate in that case?

  3. RyanCavanaugh commented on Jun 28, 2016

    @RyanCavanaugh
    Member

    the inferred type clearly has a shape that is directly incompatible with the type assertion being made

    Again, this is true of nearly every type assertion. What you're basically proposing is that

    let x: HTMLDivElement;
    x = <HTMLDivElement>document.getElementById('myDiv');

    be an error because HTMLElement is missing things from HTMLDivElement. But that's why you wrote the type assertion in the first place!

  4. mindplay-dk commented on Jun 28, 2016

    @mindplay-dk
    Author

    The compiler can't know precisely what comes out of getElementById(), or any other method.

    But in the case where I'm directly casting an object literal, it knows precisely what properties that object literal has; there's no way the assertion in the two first examples could be correct, it's guaranteed to fail.

    An object literal with a type-cast is kind of like a construction, and if that object literal is missing any properties, there's no way that results in an object that is valid for that assertion.

    Unless I'm missing something?

  5. RyanCavanaugh commented on Jun 28, 2016

    @RyanCavanaugh
    Member

    I guess we fundamentally disagree on what a type assertion is used for. My take is, a type assertion is there to let you do things you normally wouldn't be able to do. If you don't want unsafe coercions to take place, don't write a type assertion there! Adding new errors around type assertions that are plausibly correct seems counter to the very goal of a type assertion.

  6. mindplay-dk commented on Jun 30, 2016

    @mindplay-dk
    Author

    That all makes sense, and I don't think we fundamentally disagree - I'm only talking about the the case where a type-cast is being applied directly to an object literal, because that's kind of like an informal/dynamic constructor, and it's a common JS pattern, constructing something with a known shape but with no formal constructor.

    Anyhow, yeah, maybe what I'm describing isn't actually a type-cast at all - maybe it's a different feature altogether, something that shouldn't get mixed up with type-casts... it just felt like the natural thing to reach for, and it was kind of surprising to me when it didn't work - but maybe that's just me ;-)

  7. locked and limited conversation to collaborators on Jun 19, 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

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions