{"action":"opened","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/11104","repository_url":"https://api.github.com/repos/Microsoft/TypeScript","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/11104/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/11104/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/11104/events","html_url":"https://github.com/Microsoft/TypeScript/issues/11104","id":178954095,"number":11104,"title":"Design Meeting Notes, 9/23/2016","user":{"login":"mhegazy","id":8000722,"avatar_url":"https://avatars.githubusercontent.com/u/8000722?v=3","gravatar_id":"","url":"https://api.github.com/users/mhegazy","html_url":"https://github.com/mhegazy","followers_url":"https://api.github.com/users/mhegazy/followers","following_url":"https://api.github.com/users/mhegazy/following{/other_user}","gists_url":"https://api.github.com/users/mhegazy/gists{/gist_id}","starred_url":"https://api.github.com/users/mhegazy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhegazy/subscriptions","organizations_url":"https://api.github.com/users/mhegazy/orgs","repos_url":"https://api.github.com/users/mhegazy/repos","events_url":"https://api.github.com/users/mhegazy/events{/privacy}","received_events_url":"https://api.github.com/users/mhegazy/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Design%20Notes","name":"Design Notes","color":"bfdadc"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-09-23T19:20:01Z","updated_at":"2016-09-23T19:20:01Z","closed_at":null,"body":"# Literal types -- cont'd\r\n\r\n* Issue: https://github.com/Microsoft/TypeScript/issues/10898\r\n\r\n* Issue #10898 has a good example. `FAILURE` is a type that was explicitly declared, but assigning it to a let makes it disappear.\r\n\r\n## Some setup:\r\n\r\n- every literal has a \"domain\", for instance `true` and `false` have a domain, which is `boolean`\r\n- declaring `let x = true` intends to make `x` go to the domain of hte literal type, which is boolean\r\n- same goes for enums\r\n- the problem with string and numeric literal types, the domain is **all** strings or numbers, and there is no way to declare a subset of this domain\r\n- `type Direction = \"up\" | \"down\" | \"left\" | \"right\"` declares a subdomain, yet when we widen we loose this information, and in a sense we do not distinguish values of this type from any other string\r\n  ```ts\r\nfunction getEvent(): Event;\r\nconst e = getEvent();  // e is Event\r\nlet v = e;  // now v is string!!!\r\n`  ``\r\n\r\n## Proposal:\r\n\r\n- intuition is that named type aliases is a declaration of intent by the user to cleave a sub-domain of all literal types..\r\n  ```ts\r\nconst c1 = \"foo\";\r\nconst c2 = \"bar\";\r\n\r\nconst c3 = cond ? c1 : c2;\r\nconst c4: FooOrBar = cond c1 : c2;  \r\n\r\nlet x = c3;\r\nlet y = c4;\r\n  ```\r\n\r\nthere is some distinction about `c3` and `c4`. arguably `c4` has clearer intent. widening it would not be \r\n\r\n- track \"freshness\" of a literal type. a literal type with a type annotation is considered to not be \"fresh\", where as one that is inferred is considered as \"fresh\".\r\n- freshness is tracked on the type throughout the system\r\n- a fresh literal is assignable and sub-type of its \"unfresh\" version\r\n- the only difference is that fresh widens to to string/number, where as the other doe not.\r\n\r\n- so:\r\n```ts\r\n// A type annotation does not cause widening\r\ntype Result<T> = T | \"FAILURE\";\r\nfunction doWork<T>():Result<T>;\r\nlet x = doWork<number>(); // number | \"FAILURE\";\r\n\r\n// otherwise widening happen\r\nfunction doWork2<T>() {\r\n    return cond ? T : \"FAILURE\";\r\n}\r\nlet y = doWork2();  // number | string;\r\n```\r\n\r\n## what to do with declaration emitter\r\n\r\n```ts\r\nconst FAILURE = \"FAILURE\"; \r\n```\r\n\r\nemits a declaration file as:\r\n\r\n```ts\r\ndeclare const FAILURE: \"FAILURE\"; \r\n```\r\n\r\nwhich is semantically different from the original, since the original has a fresh `\"FAILURE\"` type, that widens, but the second does not widen.\r\n\r\n- this is only applicable for numeric and string literal types, and not enums or booleans.\r\nso:\r\n  ```ts\r\nconst t: true = true;\r\nlet x = t; // x is a boolean still\r\n  ```\r\nOptions:\r\n\r\n- allow initialization in constant declarations in ambient context.. e.g. \r\n```ts\r\ndeclare const FAILURE  = \"FAILURE\";\r\n```\r\n  - Q: is this too much for users to think about when writing a .d.ts?\r\n  - A: if you want to expose the value of a constant, add it as an initializer, other wise, it is just a symbolic string\r\n  - Q: What about function return types\r\n  - A: we always widen for these, so no confusion\r\n\r\n- widen when writing to the .d.ts, e.g.\r\n```ts\r\ndeclare const FAILURE: string;\r\n```\r\n   - Seems like a fine approach\r\n   - can always allow initializers later on.\r\n\r\n\r\n## Widening literal types for properties\r\n- Issue https://github.com/Microsoft/TypeScript/issues/11054\r\n\r\n- Now that we add literal freshness, do we need to widen on property assignment?\r\n- Can we just do what we do for `null` and `undefined`?\r\n- in this example a deeper issue is that we do not use return type as inference position\r\n - we have heard this multiple times. we should try this out first\r\n- this is the same as:\r\n ```ts\r\nlet x = { type: \"folder\" };\r\nlet a: FolderContentItem = x; // Error today anyways\r\n ```\r\nsimilarly a const would not work:\r\n ```ts\r\nconst x = { type: \"folder\" };\r\nlet a: FolderContentItem = x; // Still an error\r\n ```\r\n\r\n# Strict relationship for literal types (https://github.com/Microsoft/TypeScript/issues/10120)\r\n\r\n- `<` and `>` do not make much sense to be that strict. you should be able to compare `1` > `2`.\r\n- `===` and `==` do make sense. we know that `true === false` is guaranteed to fail all the time.\r\n\r\n## proposal: \r\n- for `<` like operators, widen the literal types to thier base types before doing the check.\r\n\r\n"}}
{"actor":{"display_login":"mhegazy"}}