From c8a66e06a9dc4c5bfdb87b447c7ce56c624b0d61 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 17 Jul 2024 07:14:31 -0700 Subject: [PATCH] Add more tests --- .../reference/enforceReadonly1.errors.txt | 23 +- .../reference/enforceReadonly1.symbols | 232 ++++++++++-------- .../reference/enforceReadonly1.types | 56 +++++ tests/cases/compiler/enforceReadonly1.ts | 19 ++ 4 files changed, 232 insertions(+), 98 deletions(-) diff --git a/tests/baselines/reference/enforceReadonly1.errors.txt b/tests/baselines/reference/enforceReadonly1.errors.txt index 39764796401..7031232f9fd 100644 --- a/tests/baselines/reference/enforceReadonly1.errors.txt +++ b/tests/baselines/reference/enforceReadonly1.errors.txt @@ -14,8 +14,8 @@ enforceReadonly1.ts(53,11): error TS2430: Interface 'D2' incorrectly extends int Property 'x' is 'readonly' in the source but not in the target. enforceReadonly1.ts(61,7): error TS2415: Class 'D3' incorrectly extends base class 'B3'. Property 'x' is 'readonly' in the source but not in the target. -enforceReadonly1.ts(100,3): error TS2540: Cannot assign to 'value' because it is a read-only property. -enforceReadonly1.ts(102,5): error TS2322: Type 'ImmutableValue' is not assignable to type 'MutableValue'. +enforceReadonly1.ts(119,3): error TS2540: Cannot assign to 'value' because it is a read-only property. +enforceReadonly1.ts(121,5): error TS2322: Type 'ImmutableValue' is not assignable to type 'MutableValue'. Property 'value' is 'readonly' in the source but not in the target. @@ -110,6 +110,25 @@ enforceReadonly1.ts(102,5): error TS2322: Type 'ImmutableValue' is not a readonly x = 1; } + // readonly is not enforced in comparable relation + + type Foo = { + readonly a: string | undefined; + readonly b: number | undefined; + } + + type Bar = { + a: string; + } + + function f5(foo: Foo, bar: Bar) { + return foo === bar; + } + + function f6(a: string) { + return { a } as Foo; + } + // A const assertion means "as const as possible" without violating constraints const x1 = { a: "hello", b: 42 }; diff --git a/tests/baselines/reference/enforceReadonly1.symbols b/tests/baselines/reference/enforceReadonly1.symbols index 9d99e846bdf..383ed1a089d 100644 --- a/tests/baselines/reference/enforceReadonly1.symbols +++ b/tests/baselines/reference/enforceReadonly1.symbols @@ -180,164 +180,204 @@ class D3 extends B3 { // Error >x : Symbol(D3.x, Decl(enforceReadonly1.ts, 60, 21)) } +// readonly is not enforced in comparable relation + +type Foo = { +>Foo : Symbol(Foo, Decl(enforceReadonly1.ts, 62, 1)) + + readonly a: string | undefined; +>a : Symbol(a, Decl(enforceReadonly1.ts, 66, 12)) + + readonly b: number | undefined; +>b : Symbol(b, Decl(enforceReadonly1.ts, 67, 35)) +} + +type Bar = { +>Bar : Symbol(Bar, Decl(enforceReadonly1.ts, 69, 1)) + + a: string; +>a : Symbol(a, Decl(enforceReadonly1.ts, 71, 12)) +} + +function f5(foo: Foo, bar: Bar) { +>f5 : Symbol(f5, Decl(enforceReadonly1.ts, 73, 1)) +>foo : Symbol(foo, Decl(enforceReadonly1.ts, 75, 12)) +>Foo : Symbol(Foo, Decl(enforceReadonly1.ts, 62, 1)) +>bar : Symbol(bar, Decl(enforceReadonly1.ts, 75, 21)) +>Bar : Symbol(Bar, Decl(enforceReadonly1.ts, 69, 1)) + + return foo === bar; +>foo : Symbol(foo, Decl(enforceReadonly1.ts, 75, 12)) +>bar : Symbol(bar, Decl(enforceReadonly1.ts, 75, 21)) +} + +function f6(a: string) { +>f6 : Symbol(f6, Decl(enforceReadonly1.ts, 77, 1)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 79, 12)) + + return { a } as Foo; +>a : Symbol(a, Decl(enforceReadonly1.ts, 80, 12)) +>Foo : Symbol(Foo, Decl(enforceReadonly1.ts, 62, 1)) +} + // A const assertion means "as const as possible" without violating constraints const x1 = { a: "hello", b: 42 }; ->x1 : Symbol(x1, Decl(enforceReadonly1.ts, 66, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 66, 12)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 66, 24)) +>x1 : Symbol(x1, Decl(enforceReadonly1.ts, 85, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 85, 12)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 85, 24)) const x2 = { a: "hello", b: 42 } as const; ->x2 : Symbol(x2, Decl(enforceReadonly1.ts, 67, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 67, 12)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 67, 24)) +>x2 : Symbol(x2, Decl(enforceReadonly1.ts, 86, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 86, 12)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 86, 24)) >const : Symbol(const) const y1: { a: string, b: number } = { a: "hello", b: 42 }; ->y1 : Symbol(y1, Decl(enforceReadonly1.ts, 69, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 69, 11)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 69, 22)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 69, 38)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 69, 50)) +>y1 : Symbol(y1, Decl(enforceReadonly1.ts, 88, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 88, 11)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 88, 22)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 88, 38)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 88, 50)) const y2: { a: string, b: number } = { a: "hello", b: 42 } as const; ->y2 : Symbol(y2, Decl(enforceReadonly1.ts, 70, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 70, 11)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 70, 22)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 70, 38)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 70, 50)) +>y2 : Symbol(y2, Decl(enforceReadonly1.ts, 89, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 89, 11)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 89, 22)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 89, 38)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 89, 50)) >const : Symbol(const) const y3: { a: string, readonly b: number } = { a: "hello", b: 42 }; ->y3 : Symbol(y3, Decl(enforceReadonly1.ts, 71, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 71, 11)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 71, 22)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 71, 47)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 71, 59)) +>y3 : Symbol(y3, Decl(enforceReadonly1.ts, 90, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 90, 11)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 90, 22)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 90, 47)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 90, 59)) const y4: Record = { a: 1, b: 2 } as const; ->y4 : Symbol(y4, Decl(enforceReadonly1.ts, 72, 5)) +>y4 : Symbol(y4, Decl(enforceReadonly1.ts, 91, 5)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 72, 37)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 72, 43)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 91, 37)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 91, 43)) >const : Symbol(const) declare function f10(obj: T): T; ->f10 : Symbol(f10, Decl(enforceReadonly1.ts, 72, 60)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 74, 21)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 74, 24)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 74, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 74, 21)) +>f10 : Symbol(f10, Decl(enforceReadonly1.ts, 91, 60)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 93, 21)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 93, 24)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 93, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 93, 21)) declare function f11(obj: T): T; ->f11 : Symbol(f11, Decl(enforceReadonly1.ts, 74, 35)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 75, 21)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 75, 30)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 75, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 75, 21)) +>f11 : Symbol(f11, Decl(enforceReadonly1.ts, 93, 35)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 94, 21)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 94, 30)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 94, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 94, 21)) declare function f12(obj: T): T; ->f12 : Symbol(f12, Decl(enforceReadonly1.ts, 75, 41)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 76, 21)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 76, 38)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 76, 49)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 76, 63)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 76, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 76, 21)) +>f12 : Symbol(f12, Decl(enforceReadonly1.ts, 94, 41)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 95, 21)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 95, 38)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 95, 49)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 95, 63)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 95, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 95, 21)) declare function f13(obj: T): T; ->f13 : Symbol(f13, Decl(enforceReadonly1.ts, 76, 74)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 77, 21)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 77, 38)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 77, 49)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 77, 72)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 77, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 77, 21)) +>f13 : Symbol(f13, Decl(enforceReadonly1.ts, 95, 74)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 96, 21)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 96, 38)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 96, 49)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 96, 72)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 96, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 96, 21)) declare function f14>(obj: T): T; ->f14 : Symbol(f14, Decl(enforceReadonly1.ts, 77, 83)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 78, 21)) +>f14 : Symbol(f14, Decl(enforceReadonly1.ts, 96, 83)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 97, 21)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 78, 62)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 78, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 78, 21)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 97, 62)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 97, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 97, 21)) declare function f15>>(obj: T): T; ->f15 : Symbol(f15, Decl(enforceReadonly1.ts, 78, 73)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 79, 21)) +>f15 : Symbol(f15, Decl(enforceReadonly1.ts, 97, 73)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 98, 21)) >Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 79, 72)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 79, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 79, 21)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 98, 72)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 98, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 98, 21)) f10({ a: "hello", b: 42 }); // { a: string; b: number; } ->f10 : Symbol(f10, Decl(enforceReadonly1.ts, 72, 60)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 81, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 81, 17)) +>f10 : Symbol(f10, Decl(enforceReadonly1.ts, 91, 60)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 100, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 100, 17)) f11({ a: "hello", b: 42 }); // { readonly a: "hello"; readonly b: 42; } ->f11 : Symbol(f11, Decl(enforceReadonly1.ts, 74, 35)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 82, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 82, 17)) +>f11 : Symbol(f11, Decl(enforceReadonly1.ts, 93, 35)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 101, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 101, 17)) f12({ a: "hello", b: 42 }); // { a: "hello"; b: 42; } ->f12 : Symbol(f12, Decl(enforceReadonly1.ts, 75, 41)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 83, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 83, 17)) +>f12 : Symbol(f12, Decl(enforceReadonly1.ts, 94, 41)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 102, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 102, 17)) f13({ a: "hello", b: 42 }); // { a: "hello"; readonly b: 42; } ->f13 : Symbol(f13, Decl(enforceReadonly1.ts, 76, 74)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 84, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 84, 17)) +>f13 : Symbol(f13, Decl(enforceReadonly1.ts, 95, 74)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 103, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 103, 17)) f14({ a: "hello", b: 42 }); // { a: "hello"; b: 42; } ->f14 : Symbol(f14, Decl(enforceReadonly1.ts, 77, 83)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 85, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 85, 17)) +>f14 : Symbol(f14, Decl(enforceReadonly1.ts, 96, 83)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 104, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 104, 17)) f15({ a: "hello", b: 42 }); // { readonly a: "hello"; readonly b: 42; } ->f15 : Symbol(f15, Decl(enforceReadonly1.ts, 78, 73)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 86, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 86, 17)) +>f15 : Symbol(f15, Decl(enforceReadonly1.ts, 97, 73)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 105, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 105, 17)) // https://github.com/microsoft/TypeScript/issues/13347 interface MutableValue { ->MutableValue : Symbol(MutableValue, Decl(enforceReadonly1.ts, 86, 27)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 90, 23)) +>MutableValue : Symbol(MutableValue, Decl(enforceReadonly1.ts, 105, 27)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 109, 23)) value: T; ->value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 90, 27)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 90, 23)) +>value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 109, 27)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 109, 23)) } interface ImmutableValue { ->ImmutableValue : Symbol(ImmutableValue, Decl(enforceReadonly1.ts, 92, 1)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 94, 25)) +>ImmutableValue : Symbol(ImmutableValue, Decl(enforceReadonly1.ts, 111, 1)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 113, 25)) readonly value: T; ->value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 94, 29)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 94, 25)) +>value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 113, 29)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 113, 25)) } let i: ImmutableValue = { value: "hi" }; ->i : Symbol(i, Decl(enforceReadonly1.ts, 98, 3)) ->ImmutableValue : Symbol(ImmutableValue, Decl(enforceReadonly1.ts, 92, 1)) ->value : Symbol(value, Decl(enforceReadonly1.ts, 98, 33)) +>i : Symbol(i, Decl(enforceReadonly1.ts, 117, 3)) +>ImmutableValue : Symbol(ImmutableValue, Decl(enforceReadonly1.ts, 111, 1)) +>value : Symbol(value, Decl(enforceReadonly1.ts, 117, 33)) i.value = "Excellent, I can't change it"; // Error ->i.value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 94, 29)) ->i : Symbol(i, Decl(enforceReadonly1.ts, 98, 3)) ->value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 94, 29)) +>i.value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 113, 29)) +>i : Symbol(i, Decl(enforceReadonly1.ts, 117, 3)) +>value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 113, 29)) let m: MutableValue = i; // Error ->m : Symbol(m, Decl(enforceReadonly1.ts, 101, 3)) ->MutableValue : Symbol(MutableValue, Decl(enforceReadonly1.ts, 86, 27)) ->i : Symbol(i, Decl(enforceReadonly1.ts, 98, 3)) +>m : Symbol(m, Decl(enforceReadonly1.ts, 120, 3)) +>MutableValue : Symbol(MutableValue, Decl(enforceReadonly1.ts, 105, 27)) +>i : Symbol(i, Decl(enforceReadonly1.ts, 117, 3)) m.value = "Oh dear, I can change it"; ->m.value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 90, 27)) ->m : Symbol(m, Decl(enforceReadonly1.ts, 101, 3)) ->value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 90, 27)) +>m.value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 109, 27)) +>m : Symbol(m, Decl(enforceReadonly1.ts, 120, 3)) +>value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 109, 27)) diff --git a/tests/baselines/reference/enforceReadonly1.types b/tests/baselines/reference/enforceReadonly1.types index 3a2425ae5c6..b9a790466e5 100644 --- a/tests/baselines/reference/enforceReadonly1.types +++ b/tests/baselines/reference/enforceReadonly1.types @@ -265,6 +265,62 @@ class D3 extends B3 { // Error > : ^ } +// readonly is not enforced in comparable relation + +type Foo = { +>Foo : Foo +> : ^^^ + + readonly a: string | undefined; +>a : string | undefined +> : ^^^^^^^^^^^^^^^^^^ + + readonly b: number | undefined; +>b : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +} + +type Bar = { +>Bar : Bar +> : ^^^ + + a: string; +>a : string +> : ^^^^^^ +} + +function f5(foo: Foo, bar: Bar) { +>f5 : (foo: Foo, bar: Bar) => boolean +> : ^ ^^ ^^ ^^ ^^^^^^^^^^^^ +>foo : Foo +> : ^^^ +>bar : Bar +> : ^^^ + + return foo === bar; +>foo === bar : boolean +> : ^^^^^^^ +>foo : Foo +> : ^^^ +>bar : Bar +> : ^^^ +} + +function f6(a: string) { +>f6 : (a: string) => Foo +> : ^ ^^ ^^^^^ +>a : string +> : ^^^^^^ + + return { a } as Foo; +>{ a } as Foo : Foo +> : ^^^ +>{ a } : { a: string; } +> : ^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +} + // A const assertion means "as const as possible" without violating constraints const x1 = { a: "hello", b: 42 }; diff --git a/tests/cases/compiler/enforceReadonly1.ts b/tests/cases/compiler/enforceReadonly1.ts index 5801c55189c..ef8461cb801 100644 --- a/tests/cases/compiler/enforceReadonly1.ts +++ b/tests/cases/compiler/enforceReadonly1.ts @@ -66,6 +66,25 @@ class D3 extends B3 { // Error readonly x = 1; } +// readonly is not enforced in comparable relation + +type Foo = { + readonly a: string | undefined; + readonly b: number | undefined; +} + +type Bar = { + a: string; +} + +function f5(foo: Foo, bar: Bar) { + return foo === bar; +} + +function f6(a: string) { + return { a } as Foo; +} + // A const assertion means "as const as possible" without violating constraints const x1 = { a: "hello", b: 42 };