{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/7040","repository_url":"https://api.github.com/repos/Microsoft/TypeScript","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/7040/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/7040/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/7040/events","html_url":"https://github.com/Microsoft/TypeScript/issues/7040","id":133138795,"number":7040,"title":"Suggestion: provide error/warning for always-true type guards / unreachable else blocks","user":{"login":"yortus","id":1252361,"avatar_url":"https://avatars.githubusercontent.com/u/1252361?v=3","gravatar_id":"","url":"https://api.github.com/users/yortus","html_url":"https://github.com/yortus","followers_url":"https://api.github.com/users/yortus/followers","following_url":"https://api.github.com/users/yortus/following{/other_user}","gists_url":"https://api.github.com/users/yortus/gists{/gist_id}","starred_url":"https://api.github.com/users/yortus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yortus/subscriptions","organizations_url":"https://api.github.com/users/yortus/orgs","repos_url":"https://api.github.com/users/yortus/repos","events_url":"https://api.github.com/users/yortus/events{/privacy}","received_events_url":"https://api.github.com/users/yortus/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":13,"created_at":"2016-02-12T01:56:25Z","updated_at":"2016-02-12T15:48:47Z","closed_at":null,"body":"EDIT: the original title was 'Type guards sensitive to type declaration order?', but after some discussion (see comments below) it's clearly not about declaration order, it's really about the behaviour of type guards that always return true because they match all types in the union, leading to unreachable `else` branches.\r\n\r\n---\r\n\r\n\r\n```typescript\r\n// CASE 1:\r\ntype A = {x;y} // NB: assignable to B\r\ntype B = {x}\r\nfunction isA(arg: A|B): arg is A { return true; }\r\nlet ab: A|B;\r\nif (isA(ab)) {\r\n    ab // ab has type A here\r\n}\r\nelse {\r\n    ab // ab has type B here\r\n}\r\n\r\n\r\n// CASE 2: identical to above except order of type declarations reversed\r\ntype C = {x}\r\ntype D = {x;y} // NB: assignable to C\r\nfunction isC(arg: C|D): arg is C { return true; }\r\nlet cd: C|D;\r\nif (isC(cd)) {\r\n    cd // cd has type C here\r\n}\r\nelse {\r\n    cd // cd has type D|C here     <== TYPE NOT NARROWED HERE\r\n}\r\n```\r\n\r\nThese two examples both involve a union of two types where one is assignable to the other.\r\n\r\nThe examples are identical except for the order of declaration of the two types. In the first case, the type is narrowed in both parts of the `if` statement. In the second case, it's only narrowed in one part of the `if` statement.\r\n"},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/183382100","html_url":"https://github.com/Microsoft/TypeScript/issues/7040#issuecomment-183382100","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/7040","id":183382100,"user":{"login":"tinganho","id":1324476,"avatar_url":"https://avatars.githubusercontent.com/u/1324476?v=3","gravatar_id":"","url":"https://api.github.com/users/tinganho","html_url":"https://github.com/tinganho","followers_url":"https://api.github.com/users/tinganho/followers","following_url":"https://api.github.com/users/tinganho/following{/other_user}","gists_url":"https://api.github.com/users/tinganho/gists{/gist_id}","starred_url":"https://api.github.com/users/tinganho/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tinganho/subscriptions","organizations_url":"https://api.github.com/users/tinganho/orgs","repos_url":"https://api.github.com/users/tinganho/repos","events_url":"https://api.github.com/users/tinganho/events{/privacy}","received_events_url":"https://api.github.com/users/tinganho/received_events","type":"User","site_admin":false},"created_at":"2016-02-12T15:48:47Z","updated_at":"2016-02-12T15:48:47Z","body":">function isDog2(x: Dog|Pug): x is Dog {/***/}              // WARN - no narrowing takes place\r\n\r\n@yortus I think I didn't explain my suggestion so well. My suggestion was to allow the above and have a working solution that could narrow it down to `Dog` if you pass in `Dog|Pug`. Since I think many stumble upon this issue.\r\n\r\nI think it would be more predictable, since it is a more symmetric solution(referring to OP). Or what do you think?"}}