From 3ee4e91231bfcaeec182f5213bdcc14b8d7ccfdb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 25 Apr 2024 12:24:34 -0700 Subject: [PATCH] Add more tests --- .../reference/enforceReadonly1.errors.txt | 37 ++- .../reference/enforceReadonly1.symbols | 273 ++++++++++-------- .../reference/enforceReadonly1.types | 58 ++++ tests/cases/compiler/enforceReadonly1.ts | 13 + 4 files changed, 251 insertions(+), 130 deletions(-) diff --git a/tests/baselines/reference/enforceReadonly1.errors.txt b/tests/baselines/reference/enforceReadonly1.errors.txt index 48508bd124e..b526236c3ef 100644 --- a/tests/baselines/reference/enforceReadonly1.errors.txt +++ b/tests/baselines/reference/enforceReadonly1.errors.txt @@ -6,16 +6,16 @@ enforceReadonly1.ts(17,5): error TS2322: Type 'T' is not assignable to type 'Mut enforceReadonly1.ts(18,5): error TS2322: Type 'Readonly' is not assignable to type 'Mutable'. enforceReadonly1.ts(20,5): error TS2322: Type 'Readonly' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'Readonly'. -enforceReadonly1.ts(31,11): error TS2430: Interface 'D1' incorrectly extends interface 'B1'. - Property 'x' is 'readonly' in the source but not in the target. -enforceReadonly1.ts(40,11): error TS2430: Interface 'D2' incorrectly extends interface 'B2'. - Property 'x' is 'readonly' in the source but not in the target. -enforceReadonly1.ts(48,7): error TS2415: Class 'D3' incorrectly extends base class 'B3'. - Property 'x' is 'readonly' in the source but not in the target. -enforceReadonly1.ts(56,7): error TS2415: Class 'D4' incorrectly extends base class 'B4'. +enforceReadonly1.ts(29,5): error TS2322: Type '{ readonly foo: () => void; }' is not assignable to type '{ foo: () => void; }'. Property 'foo' is 'readonly' in the source but not in the target. -enforceReadonly1.ts(95,3): error TS2540: Cannot assign to 'value' because it is a read-only property. -enforceReadonly1.ts(97,5): error TS2322: Type 'ImmutableValue' is not assignable to type 'MutableValue'. +enforceReadonly1.ts(44,11): error TS2430: Interface 'D1' incorrectly extends interface 'B1'. + Property 'x' is 'readonly' in the source but not in the target. +enforceReadonly1.ts(53,11): error TS2430: Interface 'D2' incorrectly extends interface 'B2'. + 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(108,3): error TS2540: Cannot assign to 'value' because it is a read-only property. +enforceReadonly1.ts(110,5): error TS2322: Type 'ImmutableValue' is not assignable to type 'MutableValue'. Property 'value' is 'readonly' in the source but not in the target. @@ -58,6 +58,22 @@ enforceReadonly1.ts(97,5): error TS2322: Type 'ImmutableValue' is not as rt = tt; } + // A read-only property is assignable to a property declared as a method + + function f3(m: { foo(): void }, p: { foo: () => void }, r: { readonly foo: () => void }) { + m = r; + p = r; // Error + ~ +!!! error TS2322: Type '{ readonly foo: () => void; }' is not assignable to type '{ foo: () => void; }'. +!!! error TS2322: Property 'foo' is 'readonly' in the source but not in the target. + } + + type Paths = string[] & { __brand__: "Paths" }; + + function f4(rp: Readonly, rs: Readonly) { + rs = rp; + } + // A derived interface may not change property from mutable to read-only interface B1 { @@ -99,9 +115,6 @@ enforceReadonly1.ts(97,5): error TS2322: Type 'ImmutableValue' is not as } class D4 extends B4 { // Error - ~~ -!!! error TS2415: Class 'D4' incorrectly extends base class 'B4'. -!!! error TS2415: Property 'foo' is 'readonly' in the source but not in the target. readonly foo = () => {} } diff --git a/tests/baselines/reference/enforceReadonly1.symbols b/tests/baselines/reference/enforceReadonly1.symbols index 15791efc00b..3a860fb8ee0 100644 --- a/tests/baselines/reference/enforceReadonly1.symbols +++ b/tests/baselines/reference/enforceReadonly1.symbols @@ -92,230 +92,267 @@ function f2(mt: Mutable, tt: T, rt: Readonly) { >tt : Symbol(tt, Decl(enforceReadonly1.ts, 15, 30)) } +// A read-only property is assignable to a property declared as a method + +function f3(m: { foo(): void }, p: { foo: () => void }, r: { readonly foo: () => void }) { +>f3 : Symbol(f3, Decl(enforceReadonly1.ts, 22, 1)) +>m : Symbol(m, Decl(enforceReadonly1.ts, 26, 12)) +>foo : Symbol(foo, Decl(enforceReadonly1.ts, 26, 16)) +>p : Symbol(p, Decl(enforceReadonly1.ts, 26, 31)) +>foo : Symbol(foo, Decl(enforceReadonly1.ts, 26, 36)) +>r : Symbol(r, Decl(enforceReadonly1.ts, 26, 55)) +>foo : Symbol(foo, Decl(enforceReadonly1.ts, 26, 60)) + + m = r; +>m : Symbol(m, Decl(enforceReadonly1.ts, 26, 12)) +>r : Symbol(r, Decl(enforceReadonly1.ts, 26, 55)) + + p = r; // Error +>p : Symbol(p, Decl(enforceReadonly1.ts, 26, 31)) +>r : Symbol(r, Decl(enforceReadonly1.ts, 26, 55)) +} + +type Paths = string[] & { __brand__: "Paths" }; +>Paths : Symbol(Paths, Decl(enforceReadonly1.ts, 29, 1)) +>__brand__ : Symbol(__brand__, Decl(enforceReadonly1.ts, 31, 25)) + +function f4(rp: Readonly, rs: Readonly) { +>f4 : Symbol(f4, Decl(enforceReadonly1.ts, 31, 47)) +>rp : Symbol(rp, Decl(enforceReadonly1.ts, 33, 12)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>Paths : Symbol(Paths, Decl(enforceReadonly1.ts, 29, 1)) +>rs : Symbol(rs, Decl(enforceReadonly1.ts, 33, 32)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) + + rs = rp; +>rs : Symbol(rs, Decl(enforceReadonly1.ts, 33, 32)) +>rp : Symbol(rp, Decl(enforceReadonly1.ts, 33, 12)) +} + // A derived interface may not change property from mutable to read-only interface B1 { ->B1 : Symbol(B1, Decl(enforceReadonly1.ts, 22, 1)) +>B1 : Symbol(B1, Decl(enforceReadonly1.ts, 35, 1)) x: number; ->x : Symbol(B1.x, Decl(enforceReadonly1.ts, 26, 14)) +>x : Symbol(B1.x, Decl(enforceReadonly1.ts, 39, 14)) } interface D1 extends B1 { // Error ->D1 : Symbol(D1, Decl(enforceReadonly1.ts, 28, 1)) ->B1 : Symbol(B1, Decl(enforceReadonly1.ts, 22, 1)) +>D1 : Symbol(D1, Decl(enforceReadonly1.ts, 41, 1)) +>B1 : Symbol(B1, Decl(enforceReadonly1.ts, 35, 1)) readonly x: number; ->x : Symbol(D1.x, Decl(enforceReadonly1.ts, 30, 25)) +>x : Symbol(D1.x, Decl(enforceReadonly1.ts, 43, 25)) } interface B2 { ->B2 : Symbol(B2, Decl(enforceReadonly1.ts, 32, 1)) +>B2 : Symbol(B2, Decl(enforceReadonly1.ts, 45, 1)) get x(): number; ->x : Symbol(B2.x, Decl(enforceReadonly1.ts, 34, 14), Decl(enforceReadonly1.ts, 35, 20)) +>x : Symbol(B2.x, Decl(enforceReadonly1.ts, 47, 14), Decl(enforceReadonly1.ts, 48, 20)) set x(value: number); ->x : Symbol(B2.x, Decl(enforceReadonly1.ts, 34, 14), Decl(enforceReadonly1.ts, 35, 20)) ->value : Symbol(value, Decl(enforceReadonly1.ts, 36, 10)) +>x : Symbol(B2.x, Decl(enforceReadonly1.ts, 47, 14), Decl(enforceReadonly1.ts, 48, 20)) +>value : Symbol(value, Decl(enforceReadonly1.ts, 49, 10)) } interface D2 extends B2 { // Error ->D2 : Symbol(D2, Decl(enforceReadonly1.ts, 37, 1)) ->B2 : Symbol(B2, Decl(enforceReadonly1.ts, 32, 1)) +>D2 : Symbol(D2, Decl(enforceReadonly1.ts, 50, 1)) +>B2 : Symbol(B2, Decl(enforceReadonly1.ts, 45, 1)) get x(): number; ->x : Symbol(D2.x, Decl(enforceReadonly1.ts, 39, 25)) +>x : Symbol(D2.x, Decl(enforceReadonly1.ts, 52, 25)) } class B3 { ->B3 : Symbol(B3, Decl(enforceReadonly1.ts, 41, 1)) +>B3 : Symbol(B3, Decl(enforceReadonly1.ts, 54, 1)) x = 0; ->x : Symbol(B3.x, Decl(enforceReadonly1.ts, 43, 10)) +>x : Symbol(B3.x, Decl(enforceReadonly1.ts, 56, 10)) } class D3 extends B3 { // Error ->D3 : Symbol(D3, Decl(enforceReadonly1.ts, 45, 1)) ->B3 : Symbol(B3, Decl(enforceReadonly1.ts, 41, 1)) +>D3 : Symbol(D3, Decl(enforceReadonly1.ts, 58, 1)) +>B3 : Symbol(B3, Decl(enforceReadonly1.ts, 54, 1)) readonly x = 1; ->x : Symbol(D3.x, Decl(enforceReadonly1.ts, 47, 21)) +>x : Symbol(D3.x, Decl(enforceReadonly1.ts, 60, 21)) } class B4 { ->B4 : Symbol(B4, Decl(enforceReadonly1.ts, 49, 1)) +>B4 : Symbol(B4, Decl(enforceReadonly1.ts, 62, 1)) foo() {} ->foo : Symbol(B4.foo, Decl(enforceReadonly1.ts, 51, 10)) +>foo : Symbol(B4.foo, Decl(enforceReadonly1.ts, 64, 10)) } class D4 extends B4 { // Error ->D4 : Symbol(D4, Decl(enforceReadonly1.ts, 53, 1)) ->B4 : Symbol(B4, Decl(enforceReadonly1.ts, 49, 1)) +>D4 : Symbol(D4, Decl(enforceReadonly1.ts, 66, 1)) +>B4 : Symbol(B4, Decl(enforceReadonly1.ts, 62, 1)) readonly foo = () => {} ->foo : Symbol(D4.foo, Decl(enforceReadonly1.ts, 55, 21)) +>foo : Symbol(D4.foo, Decl(enforceReadonly1.ts, 68, 21)) } // A const assertion means "as const as possible" without violating constraints const x1 = { a: "hello", b: 42 }; ->x1 : Symbol(x1, Decl(enforceReadonly1.ts, 61, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 61, 12)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 61, 24)) +>x1 : Symbol(x1, Decl(enforceReadonly1.ts, 74, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 74, 12)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 74, 24)) const x2 = { a: "hello", b: 42 } as const; ->x2 : Symbol(x2, Decl(enforceReadonly1.ts, 62, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 62, 12)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 62, 24)) +>x2 : Symbol(x2, Decl(enforceReadonly1.ts, 75, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 75, 12)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 75, 24)) >const : Symbol(const) const y1: { a: string, b: number } = { a: "hello", b: 42 }; ->y1 : Symbol(y1, Decl(enforceReadonly1.ts, 64, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 64, 11)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 64, 22)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 64, 38)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 64, 50)) +>y1 : Symbol(y1, Decl(enforceReadonly1.ts, 77, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 77, 11)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 77, 22)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 77, 38)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 77, 50)) const y2: { a: string, b: number } = { a: "hello", b: 42 } as const; ->y2 : Symbol(y2, Decl(enforceReadonly1.ts, 65, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 65, 11)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 65, 22)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 65, 38)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 65, 50)) +>y2 : Symbol(y2, Decl(enforceReadonly1.ts, 78, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 78, 11)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 78, 22)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 78, 38)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 78, 50)) >const : Symbol(const) const y3: { a: string, readonly b: number } = { a: "hello", b: 42 }; ->y3 : Symbol(y3, Decl(enforceReadonly1.ts, 66, 5)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 66, 11)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 66, 22)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 66, 47)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 66, 59)) +>y3 : Symbol(y3, Decl(enforceReadonly1.ts, 79, 5)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 79, 11)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 79, 22)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 79, 47)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 79, 59)) const y4: Record = { a: 1, b: 2 } as const; ->y4 : Symbol(y4, Decl(enforceReadonly1.ts, 67, 5)) +>y4 : Symbol(y4, Decl(enforceReadonly1.ts, 80, 5)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 67, 37)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 67, 43)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 80, 37)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 80, 43)) >const : Symbol(const) declare function f10(obj: T): T; ->f10 : Symbol(f10, Decl(enforceReadonly1.ts, 67, 60)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 69, 21)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 69, 24)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 69, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 69, 21)) +>f10 : Symbol(f10, Decl(enforceReadonly1.ts, 80, 60)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 82, 21)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 82, 24)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 82, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 82, 21)) declare function f11(obj: T): T; ->f11 : Symbol(f11, Decl(enforceReadonly1.ts, 69, 35)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 70, 21)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 70, 30)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 70, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 70, 21)) +>f11 : Symbol(f11, Decl(enforceReadonly1.ts, 82, 35)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 83, 21)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 83, 30)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 83, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 83, 21)) declare function f12(obj: T): T; ->f12 : Symbol(f12, Decl(enforceReadonly1.ts, 70, 41)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 71, 21)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 71, 38)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 71, 49)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 71, 63)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 71, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 71, 21)) +>f12 : Symbol(f12, Decl(enforceReadonly1.ts, 83, 41)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 84, 21)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 84, 38)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 84, 49)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 84, 63)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 84, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 84, 21)) declare function f13(obj: T): T; ->f13 : Symbol(f13, Decl(enforceReadonly1.ts, 71, 74)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 72, 21)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 72, 38)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 72, 49)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 72, 72)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 72, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 72, 21)) +>f13 : Symbol(f13, Decl(enforceReadonly1.ts, 84, 74)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 85, 21)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 85, 38)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 85, 49)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 85, 72)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 85, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 85, 21)) declare function f14>(obj: T): T; ->f14 : Symbol(f14, Decl(enforceReadonly1.ts, 72, 83)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 73, 21)) +>f14 : Symbol(f14, Decl(enforceReadonly1.ts, 85, 83)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 86, 21)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 73, 62)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 73, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 73, 21)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 86, 62)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 86, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 86, 21)) declare function f15>>(obj: T): T; ->f15 : Symbol(f15, Decl(enforceReadonly1.ts, 73, 73)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 74, 21)) +>f15 : Symbol(f15, Decl(enforceReadonly1.ts, 86, 73)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 87, 21)) >Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->obj : Symbol(obj, Decl(enforceReadonly1.ts, 74, 72)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 74, 21)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 74, 21)) +>obj : Symbol(obj, Decl(enforceReadonly1.ts, 87, 72)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 87, 21)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 87, 21)) f10({ a: "hello", b: 42 }); // { a: string; b: number; } ->f10 : Symbol(f10, Decl(enforceReadonly1.ts, 67, 60)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 76, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 76, 17)) +>f10 : Symbol(f10, Decl(enforceReadonly1.ts, 80, 60)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 89, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 89, 17)) f11({ a: "hello", b: 42 }); // { readonly a: "hello"; readonly b: 42; } ->f11 : Symbol(f11, Decl(enforceReadonly1.ts, 69, 35)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 77, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 77, 17)) +>f11 : Symbol(f11, Decl(enforceReadonly1.ts, 82, 35)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 90, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 90, 17)) f12({ a: "hello", b: 42 }); // { a: "hello"; b: 42; } ->f12 : Symbol(f12, Decl(enforceReadonly1.ts, 70, 41)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 78, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 78, 17)) +>f12 : Symbol(f12, Decl(enforceReadonly1.ts, 83, 41)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 91, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 91, 17)) f13({ a: "hello", b: 42 }); // { a: "hello"; readonly b: 42; } ->f13 : Symbol(f13, Decl(enforceReadonly1.ts, 71, 74)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 79, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 79, 17)) +>f13 : Symbol(f13, Decl(enforceReadonly1.ts, 84, 74)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 92, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 92, 17)) f14({ a: "hello", b: 42 }); // { a: "hello"; b: 42; } ->f14 : Symbol(f14, Decl(enforceReadonly1.ts, 72, 83)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 80, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 80, 17)) +>f14 : Symbol(f14, Decl(enforceReadonly1.ts, 85, 83)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 93, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 93, 17)) f15({ a: "hello", b: 42 }); // { readonly a: "hello"; readonly b: 42; } ->f15 : Symbol(f15, Decl(enforceReadonly1.ts, 73, 73)) ->a : Symbol(a, Decl(enforceReadonly1.ts, 81, 5)) ->b : Symbol(b, Decl(enforceReadonly1.ts, 81, 17)) +>f15 : Symbol(f15, Decl(enforceReadonly1.ts, 86, 73)) +>a : Symbol(a, Decl(enforceReadonly1.ts, 94, 5)) +>b : Symbol(b, Decl(enforceReadonly1.ts, 94, 17)) // https://github.com/microsoft/TypeScript/issues/13347 interface MutableValue { ->MutableValue : Symbol(MutableValue, Decl(enforceReadonly1.ts, 81, 27)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 85, 23)) +>MutableValue : Symbol(MutableValue, Decl(enforceReadonly1.ts, 94, 27)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 98, 23)) value: T; ->value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 85, 27)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 85, 23)) +>value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 98, 27)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 98, 23)) } interface ImmutableValue { ->ImmutableValue : Symbol(ImmutableValue, Decl(enforceReadonly1.ts, 87, 1)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 89, 25)) +>ImmutableValue : Symbol(ImmutableValue, Decl(enforceReadonly1.ts, 100, 1)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 102, 25)) readonly value: T; ->value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 89, 29)) ->T : Symbol(T, Decl(enforceReadonly1.ts, 89, 25)) +>value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 102, 29)) +>T : Symbol(T, Decl(enforceReadonly1.ts, 102, 25)) } let i: ImmutableValue = { value: "hi" }; ->i : Symbol(i, Decl(enforceReadonly1.ts, 93, 3)) ->ImmutableValue : Symbol(ImmutableValue, Decl(enforceReadonly1.ts, 87, 1)) ->value : Symbol(value, Decl(enforceReadonly1.ts, 93, 33)) +>i : Symbol(i, Decl(enforceReadonly1.ts, 106, 3)) +>ImmutableValue : Symbol(ImmutableValue, Decl(enforceReadonly1.ts, 100, 1)) +>value : Symbol(value, Decl(enforceReadonly1.ts, 106, 33)) i.value = "Excellent, I can't change it"; // Error ->i.value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 89, 29)) ->i : Symbol(i, Decl(enforceReadonly1.ts, 93, 3)) ->value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 89, 29)) +>i.value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 102, 29)) +>i : Symbol(i, Decl(enforceReadonly1.ts, 106, 3)) +>value : Symbol(ImmutableValue.value, Decl(enforceReadonly1.ts, 102, 29)) let m: MutableValue = i; // Error ->m : Symbol(m, Decl(enforceReadonly1.ts, 96, 3)) ->MutableValue : Symbol(MutableValue, Decl(enforceReadonly1.ts, 81, 27)) ->i : Symbol(i, Decl(enforceReadonly1.ts, 93, 3)) +>m : Symbol(m, Decl(enforceReadonly1.ts, 109, 3)) +>MutableValue : Symbol(MutableValue, Decl(enforceReadonly1.ts, 94, 27)) +>i : Symbol(i, Decl(enforceReadonly1.ts, 106, 3)) m.value = "Oh dear, I can change it"; ->m.value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 85, 27)) ->m : Symbol(m, Decl(enforceReadonly1.ts, 96, 3)) ->value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 85, 27)) +>m.value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 98, 27)) +>m : Symbol(m, Decl(enforceReadonly1.ts, 109, 3)) +>value : Symbol(MutableValue.value, Decl(enforceReadonly1.ts, 98, 27)) diff --git a/tests/baselines/reference/enforceReadonly1.types b/tests/baselines/reference/enforceReadonly1.types index ed7b863783e..9a1392791b1 100644 --- a/tests/baselines/reference/enforceReadonly1.types +++ b/tests/baselines/reference/enforceReadonly1.types @@ -151,6 +151,64 @@ function f2(mt: Mutable, tt: T, rt: Readonly) { > : ^ } +// A read-only property is assignable to a property declared as a method + +function f3(m: { foo(): void }, p: { foo: () => void }, r: { readonly foo: () => void }) { +>f3 : (m: { foo(): void; }, p: { foo: () => void; }, r: { readonly foo: () => void; }) => void +> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>m : { foo(): void; } +> : ^^^^^^^^^ ^^^ +>foo : () => void +> : ^^^^^^ +>p : { foo: () => void; } +> : ^^^^^^^ ^^^ +>foo : () => void +> : ^^^^^^ +>r : { readonly foo: () => void; } +> : ^^^^^^^^^^^^^^^^ ^^^ +>foo : () => void +> : ^^^^^^ + + m = r; +>m = r : { readonly foo: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>m : { foo(): void; } +> : ^^^^^^^^^^^^^^^^ +>r : { readonly foo: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + p = r; // Error +>p = r : { readonly foo: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>p : { foo: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^ +>r : { readonly foo: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +type Paths = string[] & { __brand__: "Paths" }; +>Paths : Paths +> : ^^^^^ +>__brand__ : "Paths" +> : ^^^^^^^ + +function f4(rp: Readonly, rs: Readonly) { +>f4 : (rp: Readonly, rs: Readonly) => void +> : ^ ^^ ^^ ^^ ^^^^^^^^^ +>rp : Readonly +> : ^^^^^^^^^^^^^^^ +>rs : readonly string[] +> : ^^^^^^^^^^^^^^^^^ + + rs = rp; +>rs = rp : Readonly +> : ^^^^^^^^^^^^^^^ +>rs : readonly string[] +> : ^^^^^^^^^^^^^^^^^ +>rp : Readonly +> : ^^^^^^^^^^^^^^^ +} + // A derived interface may not change property from mutable to read-only interface B1 { diff --git a/tests/cases/compiler/enforceReadonly1.ts b/tests/cases/compiler/enforceReadonly1.ts index 1678f8eaa61..dd2ad32274e 100644 --- a/tests/cases/compiler/enforceReadonly1.ts +++ b/tests/cases/compiler/enforceReadonly1.ts @@ -26,6 +26,19 @@ function f2(mt: Mutable, tt: T, rt: Readonly) { rt = tt; } +// A read-only property is assignable to a property declared as a method + +function f3(m: { foo(): void }, p: { foo: () => void }, r: { readonly foo: () => void }) { + m = r; + p = r; // Error +} + +type Paths = string[] & { __brand__: "Paths" }; + +function f4(rp: Readonly, rs: Readonly) { + rs = rp; +} + // A derived interface may not change property from mutable to read-only interface B1 {