Skip to content

Missing type-check on explicit cast? #9312

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mindplay-dk opened this issue Jun 22, 2016 · 6 comments
Closed

Missing type-check on explicit cast? #9312

mindplay-dk opened this issue Jun 22, 2016 · 6 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@mindplay-dk
Copy link

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?

@RyanCavanaugh
Copy link
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.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jun 22, 2016
@mhegazy mhegazy closed this as completed Jun 28, 2016
@mindplay-dk
Copy link
Author

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

@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?

@RyanCavanaugh
Copy link
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!

@mindplay-dk
Copy link
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?

@RyanCavanaugh
Copy link
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.

@mindplay-dk
Copy link
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 ;-)

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

3 participants