Skip to content

Unable to assert(implicit down cast) narrow types from intersection types with partial object types #7531

Closed

Description

TypeScript Version:

master

Code

<{a: number, b: number}>{a: <number&string>0, b: 0}; // ok
<{a: number, b: number}>{a: <number>0}; // ok
<{a: number, b: number}>{a: <number&string>0}; // error, should be able to assert

Expected behavior:

$ node built/local/tsc.js index.ts

Actual behavior:

$ node built/local/tsc.js index.ts
index.ts(3,1): error TS2352: Neither type '{ a: number & string; }' nor type '{ a: number; b: number; }' is assignable to the other.
  Property 'b' is missing in type '{ a: number & string; }'.

Activity

  1. mhegazy commented on Mar 16, 2016

    @mhegazy
    Contributor

    Do not really know how better to explain it than the error message does :)

    Neither type '{ a: number & string; }' nor type '{ a: number; b: number; }' is assignable to the other.

  2. RyanCavanaugh commented on Mar 16, 2016

    @RyanCavanaugh
    Member

    We have the rule in type assertions that your assertion has to be plausibly correct.

    In other words, you can't write this code

    var x = 'hello';
    var y = <number>x; // Nope

    because there's really no way that's true unless you've been telling some big lies about the type of something.

    So in this case, if you want this to be legal (as a suggested change, not a bug), we'd need to see some rule which a) makes this legal, b) has some compelling justification as for why it should be legal, and c) doesn't allow any random type to be asserted to any other random type.

  3. falsandtru commented on Mar 16, 2016

    @falsandtru
    ContributorAuthor

    TypeScript implicitly destructs intersection types in declarations.

    var x: number & string;
    var y: number = x;

    Why TypeScript does not have the same rule in partial object?

  4. RyanCavanaugh commented on Mar 16, 2016

    @RyanCavanaugh
    Member

    There's no implicit destructuring there, just a simple rule of assignability.

    A simpler case to think about would be something like

    interface Farm1 {
      x: Horse;
      y: Animal;
    }
    interface Farm2 {
      x: Animal;
      y: Dog;
    }
    
    var f1: Farm1;
    var f2: Farm2;
    
    f1 = <Farm1>f2;

    This assertion isn't allowed because neither Farm1 nor Farm2 is assignable to the other. You can't have one property go "up" while the other goes "down" -- either all the properties are being asserted to a supertype, or all the properties are asserted to a subtype. There's no mixing and matching allowed.

    #5300 is closely related.

  5. falsandtru commented on Mar 16, 2016

    @falsandtru
    ContributorAuthor

    I understood that. Thanks Ryan Cavanaugh (@RyanCavanaugh) .

  6. 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

    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