Microsoft/TypeScript — pull request #919 by ahejlsberg (2014-10-20 00:31:34+00:00)
Title: Require optional properties to be present in subtypes

This PR tightens subtyping rules such that optional properties are required to be present in subtypes.

We currently allow subtypes to drop optional properties. This leads to some odd effects:
```typescript
interface A { x: number; y?: number; }
interface B { x: number; z?: number; }
var a: A;
var b: B;
var c: [a, b];
```
This currently infers *either* type `A[]` *or* type `B[]` for `c` in an indeterminate manner. The old compiler promised to always pick the first type, but with union types that is no longer feasible. And even if it was, it doesn't make a whole lot of sense. It's pretty clear by inspection that A and B are different types and that neither should be a *subtype* of the other, even if they are both *assignable* to each other.

With the suggested change a subtype is no longer allowed to drop an optional property. Specifically, if a supertype T has an optional property P, then a subtype S must also have an optional or non-optional property P. For the example above this means that neither A nor B is a subtype of the other, so the type of `c` becomes `(A|B)[]` which makes a lot more sense.

I'm also changing the [relational operators](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#4.15.3) to require one operand be *assignable* to the other rather than one operand be a *subtype* of the other. This is pretty much the only place we use a subtype check with operators and it seems unnecessarily strict. In fact, the only remaining features that use subtype checks are union types and best common supertype checks in type argument inference and function return type inference. (Ok, the `instanceof` operator also checks that the right operand is a subtype of `Function`, but that's pretty immaterial.)

The change appears to have very little effect on real world code (one project, Monaco, required a few minor changes).

One change was required in the compiler itself, in a function in emitter.ts. That particular change is required because two anonymous types with properties of types that contain optional properties (subtle!) are no longer subtypes of each other. This actually shows the flip side of disallowing union types to be created for results of functions with multiple return statements--that would have been the right thing to do here. I'm still wondering if we really want to keep that rule (as opposed to just creating union types and relying on those to indicate what the problem was in case it wasn't intended).