Skip to content

Commit a0338d1

Browse files
authored
Ignore optionality in the comparable relationship (#12202)
* Added tests. * Accepted baselines. * Avoid checking for optionality in comparability checks. * Accepted baselines.
2 parents 0cda239 + 8708c89 commit a0338d1

File tree

9 files changed

+160
-1
lines changed

9 files changed

+160
-1
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7536,7 +7536,8 @@ namespace ts {
75367536
return Ternary.False;
75377537
}
75387538
result &= related;
7539-
if (sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
7539+
// When checking for comparability, be more lenient with optional properties.
7540+
if (relation !== comparableRelation && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
75407541
// TypeScript 1.0 spec (April 2014): 3.8.3
75417542
// S is a subtype of a type T, and T is a supertype of S if ...
75427543
// S' and T are object types and, for each member M in T..
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [optionalProperties01.ts]
2+
3+
interface Foo {
4+
required1: string;
5+
required2: string;
6+
optional?: string;
7+
}
8+
9+
const foo1 = { required1: "hello" } as Foo;
10+
const foo2 = { required1: "hello", optional: "bar" } as Foo;
11+
12+
13+
//// [optionalProperties01.js]
14+
var foo1 = { required1: "hello" };
15+
var foo2 = { required1: "hello", optional: "bar" };
16+
17+
18+
//// [optionalProperties01.d.ts]
19+
interface Foo {
20+
required1: string;
21+
required2: string;
22+
optional?: string;
23+
}
24+
declare const foo1: Foo;
25+
declare const foo2: Foo;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
=== tests/cases/conformance/types/typeRelationships/comparable/optionalProperties01.ts ===
2+
3+
interface Foo {
4+
>Foo : Symbol(Foo, Decl(optionalProperties01.ts, 0, 0))
5+
6+
required1: string;
7+
>required1 : Symbol(Foo.required1, Decl(optionalProperties01.ts, 1, 15))
8+
9+
required2: string;
10+
>required2 : Symbol(Foo.required2, Decl(optionalProperties01.ts, 2, 20))
11+
12+
optional?: string;
13+
>optional : Symbol(Foo.optional, Decl(optionalProperties01.ts, 3, 20))
14+
}
15+
16+
const foo1 = { required1: "hello" } as Foo;
17+
>foo1 : Symbol(foo1, Decl(optionalProperties01.ts, 7, 5))
18+
>required1 : Symbol(required1, Decl(optionalProperties01.ts, 7, 14))
19+
>Foo : Symbol(Foo, Decl(optionalProperties01.ts, 0, 0))
20+
21+
const foo2 = { required1: "hello", optional: "bar" } as Foo;
22+
>foo2 : Symbol(foo2, Decl(optionalProperties01.ts, 8, 5))
23+
>required1 : Symbol(required1, Decl(optionalProperties01.ts, 8, 14))
24+
>optional : Symbol(optional, Decl(optionalProperties01.ts, 8, 34))
25+
>Foo : Symbol(Foo, Decl(optionalProperties01.ts, 0, 0))
26+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/conformance/types/typeRelationships/comparable/optionalProperties01.ts ===
2+
3+
interface Foo {
4+
>Foo : Foo
5+
6+
required1: string;
7+
>required1 : string
8+
9+
required2: string;
10+
>required2 : string
11+
12+
optional?: string;
13+
>optional : string | undefined
14+
}
15+
16+
const foo1 = { required1: "hello" } as Foo;
17+
>foo1 : Foo
18+
>{ required1: "hello" } as Foo : Foo
19+
>{ required1: "hello" } : { required1: string; }
20+
>required1 : string
21+
>"hello" : "hello"
22+
>Foo : Foo
23+
24+
const foo2 = { required1: "hello", optional: "bar" } as Foo;
25+
>foo2 : Foo
26+
>{ required1: "hello", optional: "bar" } as Foo : Foo
27+
>{ required1: "hello", optional: "bar" } : { required1: string; optional: string; }
28+
>required1 : string
29+
>"hello" : "hello"
30+
>optional : string
31+
>"bar" : "bar"
32+
>Foo : Foo
33+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [optionalProperties02.ts]
2+
3+
interface Foo {
4+
a?: string;
5+
b: string;
6+
}
7+
8+
<Foo>{ a: undefined };
9+
10+
//// [optionalProperties02.js]
11+
({ a: undefined });
12+
13+
14+
//// [optionalProperties02.d.ts]
15+
interface Foo {
16+
a?: string;
17+
b: string;
18+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
=== tests/cases/conformance/types/typeRelationships/comparable/optionalProperties02.ts ===
2+
3+
interface Foo {
4+
>Foo : Symbol(Foo, Decl(optionalProperties02.ts, 0, 0))
5+
6+
a?: string;
7+
>a : Symbol(Foo.a, Decl(optionalProperties02.ts, 1, 15))
8+
9+
b: string;
10+
>b : Symbol(Foo.b, Decl(optionalProperties02.ts, 2, 15))
11+
}
12+
13+
<Foo>{ a: undefined };
14+
>Foo : Symbol(Foo, Decl(optionalProperties02.ts, 0, 0))
15+
>a : Symbol(a, Decl(optionalProperties02.ts, 6, 6))
16+
>undefined : Symbol(undefined)
17+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/conformance/types/typeRelationships/comparable/optionalProperties02.ts ===
2+
3+
interface Foo {
4+
>Foo : Foo
5+
6+
a?: string;
7+
>a : string | undefined
8+
9+
b: string;
10+
>b : string
11+
}
12+
13+
<Foo>{ a: undefined };
14+
><Foo>{ a: undefined } : Foo
15+
>Foo : Foo
16+
>{ a: undefined } : { a: undefined; }
17+
>a : undefined
18+
>undefined : undefined
19+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// @strictNullChecks: true
2+
// @declaration: true
3+
4+
interface Foo {
5+
required1: string;
6+
required2: string;
7+
optional?: string;
8+
}
9+
10+
const foo1 = { required1: "hello" } as Foo;
11+
const foo2 = { required1: "hello", optional: "bar" } as Foo;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @strictNullChecks: true
2+
// @declaration: true
3+
4+
interface Foo {
5+
a?: string;
6+
b: string;
7+
}
8+
9+
<Foo>{ a: undefined };

0 commit comments

Comments
 (0)