{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3203","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3203/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3203/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3203/events","html_url":"https://github.com/Microsoft/TypeScript/issues/3203","id":77805419,"number":3203,"title":"JSX in TypeScript","user":{"login":"RyanCavanaugh","id":6685088,"avatar_url":"https://avatars.githubusercontent.com/u/6685088?v=3","gravatar_id":"","url":"https://api.github.com/users/RyanCavanaugh","html_url":"https://github.com/RyanCavanaugh","followers_url":"https://api.github.com/users/RyanCavanaugh/followers","following_url":"https://api.github.com/users/RyanCavanaugh/following{/other_user}","gists_url":"https://api.github.com/users/RyanCavanaugh/gists{/gist_id}","starred_url":"https://api.github.com/users/RyanCavanaugh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RyanCavanaugh/subscriptions","organizations_url":"https://api.github.com/users/RyanCavanaugh/orgs","repos_url":"https://api.github.com/users/RyanCavanaugh/repos","events_url":"https://api.github.com/users/RyanCavanaugh/events{/privacy}","received_events_url":"https://api.github.com/users/RyanCavanaugh/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Committed","name":"Committed","color":"009800"},{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Fixed","name":"Fixed","color":"bfe5bf"},{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Suggestion","name":"Suggestion","color":"006b75"}],"state":"closed","locked":false,"assignee":{"login":"RyanCavanaugh","id":6685088,"avatar_url":"https://avatars.githubusercontent.com/u/6685088?v=3","gravatar_id":"","url":"https://api.github.com/users/RyanCavanaugh","html_url":"https://github.com/RyanCavanaugh","followers_url":"https://api.github.com/users/RyanCavanaugh/followers","following_url":"https://api.github.com/users/RyanCavanaugh/following{/other_user}","gists_url":"https://api.github.com/users/RyanCavanaugh/gists{/gist_id}","starred_url":"https://api.github.com/users/RyanCavanaugh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RyanCavanaugh/subscriptions","organizations_url":"https://api.github.com/users/RyanCavanaugh/orgs","repos_url":"https://api.github.com/users/RyanCavanaugh/repos","events_url":"https://api.github.com/users/RyanCavanaugh/events{/privacy}","received_events_url":"https://api.github.com/users/RyanCavanaugh/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/Microsoft/TypeScript/milestones/8","html_url":"https://github.com/Microsoft/TypeScript/milestones/TypeScript%201.6","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/milestones/8/labels","id":900034,"number":8,"title":"TypeScript 1.6","description":"","creator":{"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},"open_issues":0,"closed_issues":279,"state":"open","created_at":"2014-12-11T05:46:12Z","updated_at":"2015-09-04T20:23:32Z","due_on":null,"closed_at":null},"comments":80,"created_at":"2015-05-18T21:06:08Z","updated_at":"2015-09-07T18:10:42Z","closed_at":"2015-06-29T22:34:09Z","body":"**Updated 7/24 with some spec changes**\r\n\r\nTODO: Add language about string indexers on props types turning off surplus attribute errors\r\n\r\n## Up-front Requirements\r\nTo use JSX expressions in a TypeScript file, you must use the `tsx` extension. Additionally, during compilation, you must specify a `--jsx <value>`. Supported values are `preserve`, which emits the JSX as-is (modulo TypeScript desugaring inside JSX Expressions), or `react`, which emits React-compatible code according to their most recent stable release.\r\n\r\n## The JSX namespace\r\nSimilar to how we have special types like `Array` and `Number` in the global namespace to represent the types of `[]` and `42`, we will add a new global *optional* namespace `JSX` with some special types in it.\r\n\r\nThis namespace has four special types in it. Let's examine them.\r\n\r\n## `JSX.Element`\r\nThe type of any `<expr />` is `JSX.Element`:\r\n```ts\r\n// x is of type JSX.Element\r\nvar x = <Something hello=\"world\" />;\r\n```\r\nIf this type does not exist, it is instead an implicit `any`.\r\n\r\n## `JSX.IntrinsicElements`\r\nWhen checking an expression of the form `<foo ...>` where `foo` begins with a lower-case letter, the type `JSX.IntrinsicElements` is examined. If that type has a property called `foo`, or a string indexer, then the *element attributes type* (see below) is the type of that property (or the type of that string indexer). This process is called *intrinsic lookup*.\r\n\r\n## `JSX.ElementClass`\r\nFor expressions of the form `<Foo ... />` or `<namespace.foo .../>` we use to *value-based lookup*: Given an expression `<Foo ... >`, find a value named `Foo` in the current lexical scope.\r\n\r\nIf no value with this name exists, an error is issued. Otherwise, we treat the type of `foo` as an *element class*. The *element class* is the constructor or factory function that produces an instance of an *element instance type*.\r\n\r\nIt is an error if the *element class* is not assignable to the type `JSX.ElementClass`, or if value-based lookup occurs and no type named `JSX.ElementClass` exists.\r\n\r\nThe *element instance type* is the return types of the first construct signatures (if present), or the first call signature (if no construct signatures are present). If the element type is `any`, the *element instance* type is `any`.\r\n\r\nIt is an error if the element class has no call or construct signatures.\r\n\r\n## `JSX.ElementAttributesProperty`\r\nGiven an *element instance type*, we need to produce a type that lists the allowed attributes for that element. We call this the *element attributes type*. For example, in a React element `<div>`, the *element attributes type* includes properties like `id`, `className`, and `onClick`.\r\n\r\nThe interface `JSX.ElementAttributesProperty` defines this process. It may have 0 properties, in which case all attributes are assumed to be valid and of type `any`, or 1 property, in which case the attributes of the element must map to the properties of the type of that property.\r\n\r\nNote that *intrinsic lookup* is not affected by `ElementClass` or `ElementAttributesProperty`.\r\n\r\n## Attribute Checking\r\n```ts\r\n<Something x={expr1} { ...spr } y={expr2} />\r\n```\r\nGiven an element attributes type `E` derived from `Something` in the above example, the attributes of the element are checked as follows:\r\n * If the attribute is a normal attribute `P` initialized with `expr`:\r\n   * If `E` has a property `P`, process `expr` with the contextual type of the type of `E.P`. Otherwise, issue an error.\r\n   * It is an error if `expr` is not assignable to `E.P`.\r\n   * Add `P` to the list of properties seen\r\n * If the attribute is a spread attribute on `expr:`\r\n   * For each property `P` in the apparent type of `spr`:\r\n     * If a later attribute assignment with the name `P` occurs (either as an explicit attribute, as shown above with `y`, or via another spread attribute), nothing happens\r\n     * If `E` has a property `P`:\r\n       * It is an error if `spr.P` is not assignable to `E.P`.\r\n       * Add `P` to the list of properties seen\r\n     * Otherwise, nothing happens\r\n * After all attributes have been processed, issue an error if any required property in `E` does not have a corresponding entry in the list of properties seen\r\n\r\n## Non-identifier attributes\r\nIf an attribute name would not be a valid identifier in JavaScript code, there need not be a corresponding property in the element attributes type. This exception does not apply to names that are invalid identifiers because they are reserved words (like `var`)."},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/138350950","html_url":"https://github.com/Microsoft/TypeScript/issues/3203#issuecomment-138350950","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3203","id":138350950,"user":{"login":"bartq","id":211570,"avatar_url":"https://avatars.githubusercontent.com/u/211570?v=3","gravatar_id":"","url":"https://api.github.com/users/bartq","html_url":"https://github.com/bartq","followers_url":"https://api.github.com/users/bartq/followers","following_url":"https://api.github.com/users/bartq/following{/other_user}","gists_url":"https://api.github.com/users/bartq/gists{/gist_id}","starred_url":"https://api.github.com/users/bartq/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bartq/subscriptions","organizations_url":"https://api.github.com/users/bartq/orgs","repos_url":"https://api.github.com/users/bartq/repos","events_url":"https://api.github.com/users/bartq/events{/privacy}","received_events_url":"https://api.github.com/users/bartq/received_events","type":"User","site_admin":false},"created_at":"2015-09-07T18:10:42Z","updated_at":"2015-09-07T18:10:42Z","body":"@joewood - thanks, cool! When, tomorrow? ;)"}}