{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3622","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3622/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3622/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3622/events","html_url":"https://github.com/Microsoft/TypeScript/pull/3622","id":90820417,"number":3622,"title":"Intersection types","user":{"login":"ahejlsberg","id":4226954,"avatar_url":"https://avatars.githubusercontent.com/u/4226954?v=3","gravatar_id":"","url":"https://api.github.com/users/ahejlsberg","html_url":"https://github.com/ahejlsberg","followers_url":"https://api.github.com/users/ahejlsberg/followers","following_url":"https://api.github.com/users/ahejlsberg/following{/other_user}","gists_url":"https://api.github.com/users/ahejlsberg/gists{/gist_id}","starred_url":"https://api.github.com/users/ahejlsberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahejlsberg/subscriptions","organizations_url":"https://api.github.com/users/ahejlsberg/orgs","repos_url":"https://api.github.com/users/ahejlsberg/repos","events_url":"https://api.github.com/users/ahejlsberg/events{/privacy}","received_events_url":"https://api.github.com/users/ahejlsberg/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/cla-not-required","name":"cla-not-required","color":"009800"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":25,"created_at":"2015-06-25T01:14:38Z","updated_at":"2015-07-03T22:55:01Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/Microsoft/TypeScript/pulls/3622","html_url":"https://github.com/Microsoft/TypeScript/pull/3622","diff_url":"https://github.com/Microsoft/TypeScript/pull/3622.diff","patch_url":"https://github.com/Microsoft/TypeScript/pull/3622.patch"},"body":"This PR implements intersection types, the logical complement of union types. A union type `A | B` represents an entity that has either type A or type B, whereas an intersection type `A & B` represents an entity that has both type A and type B.\r\n\r\n### Type Relationships\r\n\r\n* Identity: `A & A` is equivalent to `A`.\r\n* Commutativity: `A & B` is equivalent to `B & A` (except for call and construct signatures as noted below).\r\n* Associativity: `(A & B) & C` is equivalent to `A & (B & C)`.\r\n* Supertype collapsing: `A & B` is equivalent to `A` if `B` is a supertype of `A`.\r\n\r\n### Assignment compatibility\r\n\r\n* `A & B` is assignable to `X` if `A` is assignable to `X` or `B` is assignable to `X`.\r\n* `X` is assignable to `A & B` if `X` is assignable to `A` and `X` is assignable to `B`.\r\n\r\n### Properties and Index Signatures\r\n\r\nThe type `A & B` has a property `P` if `A` has a property `P` or `B` has a property `P`. If `A` has a property `P` of type `X` and `B` has a property `P` of type `Y`, then `A & B` has a property `P` of type `X & Y`.\r\n\r\nIndex signatures are similarly intersected.\r\n\r\n### Call and Construct Signatures\r\n\r\nIf `A` has a signature `F` and `B` has a signature `G`, then `A & B` has signatures `F` and `G` in that order (the order of signatures matter for purposes of overload resolution). Except for the order of signatures, the types `A & B` and `B & A` are equivalent.\r\n\r\n### Precedence\r\n\r\nSimilarly to expression operators, the `&` type operator has higher precedence than the `|` type operator. Thus `A & B | C & D` is parsed as `(A & B) | (C & D)`.\r\n\r\n### Primitive Types\r\n\r\nIt is possible to intersect primitive types (e.g. `string & number`), but it is not possible to actually create values of such types (other than `undefined`). Because such types can result from instantiation of generic types (which is performed lazily), it is not possible to consistently detect and error on the operations that create the types.\r\n\r\n### Examples\r\n\r\n```typescript\r\nfunction extend<T, U>(first: T, second: U): T & U {\r\n    let result = <T & U> {};\r\n    for (let id in first) {\r\n        result[id] = first[id];\r\n    }\r\n    for (let id in second) {\r\n        if (!result.hasOwnProperty(id)) {\r\n            result[id] = second[id];\r\n        }\r\n    }\r\n    return result;\r\n}\r\n\r\nvar x = extend({ a: \"hello\" }, { b: 42 });\r\nvar s = x.a;\r\nvar n = x.b;\r\n```\r\n\r\n```typescript\r\ntype LinkedList<T> = T & { next: LinkedList<T> };\r\n\r\ninterface Person {\r\n    name: string;\r\n}\r\n\r\nvar people: LinkedList<Person>;\r\nvar s = people.name;\r\nvar s = people.next.name;\r\nvar s = people.next.next.name;\r\nvar s = people.next.next.next.name;\r\n```\r\n\r\n```typescript\r\ninterface A { a: string }\r\ninterface B { b: string }\r\ninterface C { c: string }\r\n\r\nvar abc: A & B & C;\r\nabc.a = \"hello\";\r\nabc.b = \"hello\";\r\nabc.c = \"hello\";\r\n\r\ninterface X { x: A }\r\ninterface Y { x: B }\r\ninterface Z { x: C }\r\n\r\nvar xyz: X & Y & Z;\r\nxyz.x.a = \"hello\";\r\nxyz.x.b = \"hello\";\r\nxyz.x.c = \"hello\";\r\n\r\ntype F1 = (x: string) => string;\r\ntype F2 = (x: number) => number;\r\n\r\nvar f: F1 & F2;\r\nvar s = f(\"hello\");\r\nvar n = f(42);\r\n```\r\n\r\nFixes #1256."},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/118436117","html_url":"https://github.com/Microsoft/TypeScript/pull/3622#issuecomment-118436117","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3622","id":118436117,"user":{"login":"rotemdan","id":8589488,"avatar_url":"https://avatars.githubusercontent.com/u/8589488?v=3","gravatar_id":"","url":"https://api.github.com/users/rotemdan","html_url":"https://github.com/rotemdan","followers_url":"https://api.github.com/users/rotemdan/followers","following_url":"https://api.github.com/users/rotemdan/following{/other_user}","gists_url":"https://api.github.com/users/rotemdan/gists{/gist_id}","starred_url":"https://api.github.com/users/rotemdan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rotemdan/subscriptions","organizations_url":"https://api.github.com/users/rotemdan/orgs","repos_url":"https://api.github.com/users/rotemdan/repos","events_url":"https://api.github.com/users/rotemdan/events{/privacy}","received_events_url":"https://api.github.com/users/rotemdan/received_events","type":"User","site_admin":false},"created_at":"2015-07-03T22:55:01Z","updated_at":"2015-07-03T22:55:01Z","body":"@ahejlsberg Well, [my original post](https://github.com/Microsoft/TypeScript/pull/3622#issuecomment-117649458) was pretty much solely about the name (the first thing I wrote was that I like this feature, but don't understand the naming :) ). Then I spent a total of many hours in the span of several days with countless messages back and forth with @JsonFreeman (who was very helpful) to try and figure out how this concept of \"intersection\" relates to this operation in mathematical terms, and it turned out it does, but only for infinitely extensible types.\r\n\r\nAt some point I made [a simple example](https://github.com/Microsoft/TypeScript/pull/3622#issuecomment-118010337) that showed that in the case of strict interfaces there wouldn't necessarily be any union, complement or even intersection relationships between the resulting set of possible values, they may all be different, and applying this operation may actually make the resulting set of values be exponentially larger than the sets for the involved types (in the case of finite types such as the example I gave with booleans).\r\n\r\nI was then told that when applied to strict interfaces, the operation would have would result in the empty set or undefined - which may actually be correct mathematically, but not very useful for programming. That's was a major part of the reasoning behind all of this.. So based on what you say if the actual intention is to have it as a \"looser\" operation that's less tied to the math, that would be OK I guess, the name would still not be great but I think I'm starting to get tired of this anyway :)..\r\n\r\nAnyway, among the other things I mentioned, I think the next important one was asking: \r\n\r\n1. Whether all the potential types of results of the intersection operation would actually be expressible in plain interface declarations (i.e. plain `interface A = {..}`), especially the overloading of property types, (`interface A = {x: number; x: string}`), and if it would have a different meaning from union on the property with the same types (`{x: number | string}`) (semantically and structurally)\r\n\r\n2. You mentioned that overloading functions is actually possible in interfaces, but I keep getting a \"duplicate identifier\" errors trying to do that, but maybe I misunderstood somehow. Anyway, I'm curious If the overloading of properties and functions be supported in interface inheritance, and if they will, it seems like the logic to support it could be used define a new \"extend\" operation, that might be a useful thing on it's own (or turn out to be exactly the same as the intersection operation?). You gave some reasoning about \"no first class polymorphism\" regarding this but unfortunately I'm not familiar with that (I do understand some of the theory of programming language, but mostly the basic and pragmatic stuff..)"}}