{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/8474","repository_url":"https://api.github.com/repos/Microsoft/TypeScript","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/8474/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/8474/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/8474/events","html_url":"https://github.com/Microsoft/TypeScript/issues/8474","id":153242372,"number":8474,"title":"Overriden class member annotated with a subtype could be a recipe for disaster (by design.. ;) )","user":{"login":"malibuzios","id":17719551,"avatar_url":"https://avatars.githubusercontent.com/u/17719551?v=3","gravatar_id":"","url":"https://api.github.com/users/malibuzios","html_url":"https://github.com/malibuzios","followers_url":"https://api.github.com/users/malibuzios/followers","following_url":"https://api.github.com/users/malibuzios/following{/other_user}","gists_url":"https://api.github.com/users/malibuzios/gists{/gist_id}","starred_url":"https://api.github.com/users/malibuzios/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/malibuzios/subscriptions","organizations_url":"https://api.github.com/users/malibuzios/orgs","repos_url":"https://api.github.com/users/malibuzios/repos","events_url":"https://api.github.com/users/malibuzios/events{/privacy}","received_events_url":"https://api.github.com/users/malibuzios/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Needs%20Proposal","name":"Needs Proposal","color":"556b75"},{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Suggestion","name":"Suggestion","color":"006b75"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":12,"created_at":"2016-05-05T14:21:28Z","updated_at":"2016-05-05T18:46:36Z","closed_at":null,"body":"**TypeScript Version:** \r\n`1.9.0-dev.20160505` with both `strictNullChecks` and `noImplicitAny` enabled.\r\n\r\n**Code:**\r\n\r\n```ts\r\nclass Animal {\r\n    name: string = \"Any animal\";\r\n}\r\n\r\nclass Dog extends Animal {\r\n    name: string = \"Dog\";\r\n\r\n    bark() {\r\n        console.log(\"bark\");\r\n    }\r\n}\r\n\r\nclass AnimalCage {\r\n    member: Animal = new Animal();\r\n}\r\n\r\nclass DogCage extends AnimalCage {\r\n    member: Dog;\r\n}\r\n\r\nlet dogCage = new DogCage();\r\n\r\nif (dogCage.member != null) { // Yup, it is even checked for null or undefined, \r\n\t\t\t\t\t\t\t  // but it turned out that wasn't enough..\r\n    dogCage.member.bark(); // Bang!\r\n}\r\n```\r\n\r\n**Expected behavior:**\r\nDesign a language where inheritance actually works.\r\n(_Edit: I was felling very 'passionate' when I wrote this.. sorry :) nothing personal_)\r\n\r\n**Actual behavior:** \r\nBy design:\r\n```\r\n    dogCage.member.bark();\r\n                   ^\r\n\r\nTypeError: dogCage.member.bark is not a function\r\n    at Object.<anonymous> (C:\\X\\Documents\\Drafts\\TypeScript\\Code\\a.js:38:20)\r\n    at Module._compile (module.js:541:32)\r\n    at Object.Module._extensions..js (module.js:550:10)\r\n    at Module.load (module.js:456:32)\r\n    at tryModuleLoad (module.js:415:12)\r\n    at Function.Module._load (module.js:407:3)\r\n    at Function.Module.runMain (module.js:575:10)\r\n    at startup (node.js:159:18)\r\n    at node.js:444:3\r\n```\r\n\r\n**Resolution:**\r\n`tslint` volunteers, for the rescue!"},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/217240154","html_url":"https://github.com/Microsoft/TypeScript/issues/8474#issuecomment-217240154","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/8474","id":217240154,"user":{"login":"malibuzios","id":17719551,"avatar_url":"https://avatars.githubusercontent.com/u/17719551?v=3","gravatar_id":"","url":"https://api.github.com/users/malibuzios","html_url":"https://github.com/malibuzios","followers_url":"https://api.github.com/users/malibuzios/followers","following_url":"https://api.github.com/users/malibuzios/following{/other_user}","gists_url":"https://api.github.com/users/malibuzios/gists{/gist_id}","starred_url":"https://api.github.com/users/malibuzios/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/malibuzios/subscriptions","organizations_url":"https://api.github.com/users/malibuzios/orgs","repos_url":"https://api.github.com/users/malibuzios/repos","events_url":"https://api.github.com/users/malibuzios/events{/privacy}","received_events_url":"https://api.github.com/users/malibuzios/received_events","type":"User","site_admin":false},"created_at":"2016-05-05T18:46:36Z","updated_at":"2016-05-05T18:46:36Z","body":"@RyanCavanaugh \r\n\r\nOK, so it would also look at base classes, but what about:\r\n```ts\r\nclass A {\r\n    prop: Animal = new Animal()\r\n}\r\n\r\nclass B extends A {\r\n    prop: Dog; // would this error here that 'prop' is not initialized to an exact matching type?\r\n}\r\n```\r\nIn order to achieve this, it would need to simply test if `Animal` and `Dog` are strictly structurally identical before coming to the conclusion that `prop` was initialized in the base class.\r\n\r\nI feel this could be a significant step here (or perhaps an opportunity since nullability checks have not yet made it to production - no breaking changes involved). I also feel this would be one of those places that programmers may wonder a little what went wrong for getting this error. After all, `prop` does technically have a value, only it is for a 'less capable' type. However, they may eventually 'thank' the compiler of being 'smart' enough for noticing something that may not be completely trivial for a distracted or tired human to notice.\r\n\r\nIf the intention was for a contravariant cast, it could perhaps be done like this:\r\n```ts\r\nclass A {\r\n    prop: Animal = new Animal()\r\n}\r\n\r\nclass B extends A {\r\n\tprop: Dog;\r\n\t\r\n\tconstructor() {\r\n\t\tsuper();\r\n\t\tthis.prop = <Dog> super.prop; // this isn't valid syntax today, only used for illustration\r\n\t}\r\n}\r\n```\r\nI must say in the years I've used this language, I don't think I ever had a situation where I wanted to perform a contravariant cast from the initialized value of a base class to the more capable type in the derived class. If the intention was to initialize to `Dog` then it could simply initialize it in the derived class? why would it need to be initialized in the base class through a cast? in that case, the type of `prop` in the base class should be `Dog`? or at least `Dog | Animal`?"}}