Skip to content

Commit

Permalink
Ignore optionality in the comparable relationship (microsoft#12202)
Browse files Browse the repository at this point in the history
* Added tests.

* Accepted baselines.

* Avoid checking for optionality in comparability checks.

* Accepted baselines.
  • Loading branch information
mhegazy authored Nov 14, 2016
2 parents 0cda239 + 8708c89 commit a0338d1
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7536,7 +7536,8 @@ namespace ts {
return Ternary.False;
}
result &= related;
if (sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
// When checking for comparability, be more lenient with optional properties.
if (relation !== comparableRelation && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
// TypeScript 1.0 spec (April 2014): 3.8.3
// S is a subtype of a type T, and T is a supertype of S if ...
// S' and T are object types and, for each member M in T..
Expand Down
25 changes: 25 additions & 0 deletions tests/baselines/reference/optionalProperties01.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//// [optionalProperties01.ts]

interface Foo {
required1: string;
required2: string;
optional?: string;
}

const foo1 = { required1: "hello" } as Foo;
const foo2 = { required1: "hello", optional: "bar" } as Foo;


//// [optionalProperties01.js]
var foo1 = { required1: "hello" };
var foo2 = { required1: "hello", optional: "bar" };


//// [optionalProperties01.d.ts]
interface Foo {
required1: string;
required2: string;
optional?: string;
}
declare const foo1: Foo;
declare const foo2: Foo;
26 changes: 26 additions & 0 deletions tests/baselines/reference/optionalProperties01.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
=== tests/cases/conformance/types/typeRelationships/comparable/optionalProperties01.ts ===

interface Foo {
>Foo : Symbol(Foo, Decl(optionalProperties01.ts, 0, 0))

required1: string;
>required1 : Symbol(Foo.required1, Decl(optionalProperties01.ts, 1, 15))

required2: string;
>required2 : Symbol(Foo.required2, Decl(optionalProperties01.ts, 2, 20))

optional?: string;
>optional : Symbol(Foo.optional, Decl(optionalProperties01.ts, 3, 20))
}

const foo1 = { required1: "hello" } as Foo;
>foo1 : Symbol(foo1, Decl(optionalProperties01.ts, 7, 5))
>required1 : Symbol(required1, Decl(optionalProperties01.ts, 7, 14))
>Foo : Symbol(Foo, Decl(optionalProperties01.ts, 0, 0))

const foo2 = { required1: "hello", optional: "bar" } as Foo;
>foo2 : Symbol(foo2, Decl(optionalProperties01.ts, 8, 5))
>required1 : Symbol(required1, Decl(optionalProperties01.ts, 8, 14))
>optional : Symbol(optional, Decl(optionalProperties01.ts, 8, 34))
>Foo : Symbol(Foo, Decl(optionalProperties01.ts, 0, 0))

33 changes: 33 additions & 0 deletions tests/baselines/reference/optionalProperties01.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
=== tests/cases/conformance/types/typeRelationships/comparable/optionalProperties01.ts ===

interface Foo {
>Foo : Foo

required1: string;
>required1 : string

required2: string;
>required2 : string

optional?: string;
>optional : string | undefined
}

const foo1 = { required1: "hello" } as Foo;
>foo1 : Foo
>{ required1: "hello" } as Foo : Foo
>{ required1: "hello" } : { required1: string; }
>required1 : string
>"hello" : "hello"
>Foo : Foo

const foo2 = { required1: "hello", optional: "bar" } as Foo;
>foo2 : Foo
>{ required1: "hello", optional: "bar" } as Foo : Foo
>{ required1: "hello", optional: "bar" } : { required1: string; optional: string; }
>required1 : string
>"hello" : "hello"
>optional : string
>"bar" : "bar"
>Foo : Foo

18 changes: 18 additions & 0 deletions tests/baselines/reference/optionalProperties02.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//// [optionalProperties02.ts]

interface Foo {
a?: string;
b: string;
}

<Foo>{ a: undefined };

//// [optionalProperties02.js]
({ a: undefined });


//// [optionalProperties02.d.ts]
interface Foo {
a?: string;
b: string;
}
17 changes: 17 additions & 0 deletions tests/baselines/reference/optionalProperties02.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
=== tests/cases/conformance/types/typeRelationships/comparable/optionalProperties02.ts ===

interface Foo {
>Foo : Symbol(Foo, Decl(optionalProperties02.ts, 0, 0))

a?: string;
>a : Symbol(Foo.a, Decl(optionalProperties02.ts, 1, 15))

b: string;
>b : Symbol(Foo.b, Decl(optionalProperties02.ts, 2, 15))
}

<Foo>{ a: undefined };
>Foo : Symbol(Foo, Decl(optionalProperties02.ts, 0, 0))
>a : Symbol(a, Decl(optionalProperties02.ts, 6, 6))
>undefined : Symbol(undefined)

19 changes: 19 additions & 0 deletions tests/baselines/reference/optionalProperties02.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
=== tests/cases/conformance/types/typeRelationships/comparable/optionalProperties02.ts ===

interface Foo {
>Foo : Foo

a?: string;
>a : string | undefined

b: string;
>b : string
}

<Foo>{ a: undefined };
><Foo>{ a: undefined } : Foo
>Foo : Foo
>{ a: undefined } : { a: undefined; }
>a : undefined
>undefined : undefined

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @strictNullChecks: true
// @declaration: true

interface Foo {
required1: string;
required2: string;
optional?: string;
}

const foo1 = { required1: "hello" } as Foo;
const foo2 = { required1: "hello", optional: "bar" } as Foo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @strictNullChecks: true
// @declaration: true

interface Foo {
a?: string;
b: string;
}

<Foo>{ a: undefined };

0 comments on commit a0338d1

Please sign in to comment.