diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d34efcbe1bf..8f05f5f4e9f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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.. diff --git a/tests/baselines/reference/optionalProperties01.js b/tests/baselines/reference/optionalProperties01.js new file mode 100644 index 00000000000..a614b9e7e37 --- /dev/null +++ b/tests/baselines/reference/optionalProperties01.js @@ -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; diff --git a/tests/baselines/reference/optionalProperties01.symbols b/tests/baselines/reference/optionalProperties01.symbols new file mode 100644 index 00000000000..95c53626f6e --- /dev/null +++ b/tests/baselines/reference/optionalProperties01.symbols @@ -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)) + diff --git a/tests/baselines/reference/optionalProperties01.types b/tests/baselines/reference/optionalProperties01.types new file mode 100644 index 00000000000..20d16d4071e --- /dev/null +++ b/tests/baselines/reference/optionalProperties01.types @@ -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 + diff --git a/tests/baselines/reference/optionalProperties02.js b/tests/baselines/reference/optionalProperties02.js new file mode 100644 index 00000000000..f632c5d67a8 --- /dev/null +++ b/tests/baselines/reference/optionalProperties02.js @@ -0,0 +1,18 @@ +//// [optionalProperties02.ts] + +interface Foo { + a?: string; + b: string; +} + +{ a: undefined }; + +//// [optionalProperties02.js] +({ a: undefined }); + + +//// [optionalProperties02.d.ts] +interface Foo { + a?: string; + b: string; +} diff --git a/tests/baselines/reference/optionalProperties02.symbols b/tests/baselines/reference/optionalProperties02.symbols new file mode 100644 index 00000000000..b88f9ad7429 --- /dev/null +++ b/tests/baselines/reference/optionalProperties02.symbols @@ -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)) +} + +{ a: undefined }; +>Foo : Symbol(Foo, Decl(optionalProperties02.ts, 0, 0)) +>a : Symbol(a, Decl(optionalProperties02.ts, 6, 6)) +>undefined : Symbol(undefined) + diff --git a/tests/baselines/reference/optionalProperties02.types b/tests/baselines/reference/optionalProperties02.types new file mode 100644 index 00000000000..05e979b3972 --- /dev/null +++ b/tests/baselines/reference/optionalProperties02.types @@ -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 +} + +{ a: undefined }; +>{ a: undefined } : Foo +>Foo : Foo +>{ a: undefined } : { a: undefined; } +>a : undefined +>undefined : undefined + diff --git a/tests/cases/conformance/types/typeRelationships/comparable/optionalProperties01.ts b/tests/cases/conformance/types/typeRelationships/comparable/optionalProperties01.ts new file mode 100644 index 00000000000..d4f04d78c80 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/comparable/optionalProperties01.ts @@ -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; diff --git a/tests/cases/conformance/types/typeRelationships/comparable/optionalProperties02.ts b/tests/cases/conformance/types/typeRelationships/comparable/optionalProperties02.ts new file mode 100644 index 00000000000..21f83276d44 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/comparable/optionalProperties02.ts @@ -0,0 +1,9 @@ +// @strictNullChecks: true +// @declaration: true + +interface Foo { + a?: string; + b: string; +} + +{ a: undefined }; \ No newline at end of file