{"action":"opened","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/24590","repository_url":"https://api.github.com/repos/Microsoft/TypeScript","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/24590/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/24590/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/24590/events","html_url":"https://github.com/Microsoft/TypeScript/issues/24590","id":328651438,"node_id":"MDU6SXNzdWUzMjg2NTE0Mzg=","number":24590,"title":"Incorrectly inferred type parameter when candidate types are a subset of each other","user":{"login":"fenduru","id":1354771,"node_id":"MDQ6VXNlcjEzNTQ3NzE=","avatar_url":"https://avatars3.githubusercontent.com/u/1354771?v=4","gravatar_id":"","url":"https://api.github.com/users/fenduru","html_url":"https://github.com/fenduru","followers_url":"https://api.github.com/users/fenduru/followers","following_url":"https://api.github.com/users/fenduru/following{/other_user}","gists_url":"https://api.github.com/users/fenduru/gists{/gist_id}","starred_url":"https://api.github.com/users/fenduru/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fenduru/subscriptions","organizations_url":"https://api.github.com/users/fenduru/orgs","repos_url":"https://api.github.com/users/fenduru/repos","events_url":"https://api.github.com/users/fenduru/events{/privacy}","received_events_url":"https://api.github.com/users/fenduru/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-06-01T20:31:06Z","updated_at":"2018-06-01T20:31:06Z","closed_at":null,"author_association":"NONE","body":"Apologies for the confusing title, I'm really not sure how to describe this issue succinctly. Feel free to change the title to something more clear.\r\n\r\n<!-- Please try to reproduce the issue with `typescript@next`. It may have already been fixed. -->\r\n**TypeScript Version:**  3.0.0-dev.20180601\r\n\r\n<!-- Search terms you tried before logging this (so others can find this issue more easily) -->\r\n**Search Terms:** \r\n\r\nIncorrect type inference, widened types, candidate types, subset\r\n\r\n**Code**\r\n\r\n```ts\r\nlet foo: string = 'foo';\r\n\r\n// Use a function for indirection to prevent control flow analysis from\r\n// ignoring explicit type annotation and treating bar as number rather than string | number\r\nfunction getBar(): string | number {\r\n    return 5;\r\n}\r\n\r\nlet bar: string | number = getBar();\r\n\r\nclass Container<T> {\r\n    public saved: T;\r\n\r\n    constructor(arg: T) {\r\n        this.saved = arg;\r\n    }\r\n}\r\n\r\nfunction assign<T>(x: Container<T>, y: T) {\r\n    x.saved = y;\r\n}\r\n\r\nconst myContainer = new Container(foo);\r\n\r\nassign(myContainer, bar);\r\n\r\nconst result = myContainer.saved.toUpperCase(); // TypeErrors at runtime\r\n```\r\n\r\n**Expected behavior:**\r\n\r\nThe `assign(myContainer, bar)` should not typecheck as it is attempting to use two incompatible types for the type param `T`. `string | number` is not a common type of `string`. When one candidate type is a subset of the other, the narrowest type should be chosen for inference (leading to an error in the argument position of the wider type)\r\n\r\n**Actual behavior:**\r\n\r\n`assign<T>` is inferring `string | number` as the type of T even though that is incompatible with the type `string` that the `Container` is parameterized on. This allows the function to assign a non-string value to a string member variable, leading to runtime type errors.\r\n\r\n[**Playground Link**](https://www.typescriptlang.org/play/index.html#src=let%20foo%3A%20string%20%3D%20'foo'%3B%0D%0A%0D%0A%2F%2F%20Use%20a%20function%20for%20indirection%20to%20prevent%20control%20flow%20analysis%20from%0D%0A%2F%2F%20ignoring%20explicit%20type%20annotation%20and%20treating%20bar%20as%20number%20rather%20than%20string%20%7C%20number%0D%0Afunction%20getBar()%3A%20string%20%7C%20number%20%7B%0D%0A%20%20%20%20return%205%3B%0D%0A%7D%0D%0A%0D%0Alet%20bar%3A%20string%20%7C%20number%20%3D%20getBar()%3B%0D%0A%0D%0Aclass%20Container%3CT%3E%20%7B%0D%0A%20%20%20%20public%20saved%3A%20T%3B%0D%0A%0D%0A%20%20%20%20constructor(arg%3A%20T)%20%7B%0D%0A%20%20%20%20%20%20%20%20this.saved%20%3D%20arg%3B%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A%0D%0Afunction%20assign%3CT%3E(x%3A%20Container%3CT%3E%2C%20y%3A%20T)%20%7B%0D%0A%20%20%20%20x.saved%20%3D%20y%3B%0D%0A%7D%0D%0A%0D%0Aconst%20myContainer%20%3D%20new%20Container(foo)%3B%0D%0A%0D%0Aassign(myContainer%2C%20bar)%3B%0D%0A%0D%0Aconst%20result%20%3D%20myContainer.saved.toUpperCase()%3B%20%2F%2F%20TypeErrors%20at%20runtime)\r\n\r\n**Related Issues:** <!-- Did you find other bugs that looked similar? -->\r\n"}}
{"actor":{"display_login":"fenduru"}}