enforceReadonly1.ts(4,5): error TS2322: Type '{ readonly x: string; }' is not assignable to type '{ x: string; }'.
  Property 'x' is 'readonly' in the source but not in the target.
enforceReadonly1.ts(8,5): error TS2322: Type '{ readonly [x: string]: string; }' is not assignable to type '{ [x: string]: string; }'.
  'string' index signature is 'readonly' in the source but not in the target.
enforceReadonly1.ts(17,5): error TS2322: Type 'T' is not assignable to type 'Mutable<T>'.
enforceReadonly1.ts(18,5): error TS2322: Type 'Readonly<T>' is not assignable to type 'Mutable<T>'.
enforceReadonly1.ts(20,5): error TS2322: Type 'Readonly<T>' is not assignable to type 'T'.
  'T' could be instantiated with an arbitrary type which could be unrelated to 'Readonly<T>'.
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(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(119,3): error TS2540: Cannot assign to 'value' because it is a read-only property.
enforceReadonly1.ts(121,5): error TS2322: Type 'ImmutableValue<string>' is not assignable to type 'MutableValue<string>'.
  Property 'value' is 'readonly' in the source but not in the target.


==== enforceReadonly1.ts (11 errors) ====
    // A read-only property is not assignable to a mutable property
    
    function f1(mp: { x: string }, rp: { readonly x: string }, mx: { [x: string]: string }, rx: { readonly [x: string]: string }) {
        mp = rp;  // Error
        ~~
!!! error TS2322: Type '{ readonly x: string; }' is not assignable to type '{ x: string; }'.
!!! error TS2322:   Property 'x' is 'readonly' in the source but not in the target.
        rp = mp;
        mx = mp;
        mx = rp;
        mx = rx;  // Error
        ~~
!!! error TS2322: Type '{ readonly [x: string]: string; }' is not assignable to type '{ [x: string]: string; }'.
!!! error TS2322:   'string' index signature is 'readonly' in the source but not in the target.
        rx = mp;
        rx = rp;
        rx = mx;
    }
    
    type Mutable<T> = { -readonly [P in keyof T]: T[P] };
    
    function f2<T>(mt: Mutable<T>, tt: T, rt: Readonly<T>) {
        mt = tt;  // Error
        ~~
!!! error TS2322: Type 'T' is not assignable to type 'Mutable<T>'.
!!! related TS2208 enforceReadonly1.ts:16:13: This type parameter might need an `extends Mutable<T>` constraint.
        mt = rt;  // Error
        ~~
!!! error TS2322: Type 'Readonly<T>' is not assignable to type 'Mutable<T>'.
        tt = mt;
        tt = rt;  // Error
        ~~
!!! error TS2322: Type 'Readonly<T>' is not assignable to type 'T'.
!!! error TS2322:   'T' could be instantiated with an arbitrary type which could be unrelated to 'Readonly<T>'.
        rt = mt;
        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<Paths>, rs: Readonly<string[]>) {
        rs = rp;
    }
    
    // A derived interface may not change property from mutable to read-only
    
    interface B1 {
        x: number;
    }
    
    interface D1 extends B1 {  // Error
              ~~
!!! error TS2430: Interface 'D1' incorrectly extends interface 'B1'.
!!! error TS2430:   Property 'x' is 'readonly' in the source but not in the target.
        readonly x: number;
    }
    
    interface B2 {
        get x(): number;
        set x(value: number);
    }
    
    interface D2 extends B2 {  // Error
              ~~
!!! error TS2430: Interface 'D2' incorrectly extends interface 'B2'.
!!! error TS2430:   Property 'x' is 'readonly' in the source but not in the target.
        get x(): number;
    }
    
    class B3 {
        x = 0;
    }
    
    class D3 extends B3 {  // Error
          ~~
!!! error TS2415: Class 'D3' incorrectly extends base class 'B3'.
!!! error TS2415:   Property 'x' is 'readonly' in the source but not in the target.
        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 };
    const x2 = { a: "hello", b: 42 } as const;
    
    const y1: { a: string, b: number } = { a: "hello", b: 42 };
    const y2: { a: string, b: number } = { a: "hello", b: 42 } as const;
    const y3: { a: string, readonly b: number } = { a: "hello", b: 42 };
    const y4: Record<string, unknown> = { a: 1, b: 2 } as const;
    
    declare function f10<T>(obj: T): T;
    declare function f11<const T>(obj: T): T;
    declare function f12<const T extends { a: string, b: number }>(obj: T): T;
    declare function f13<const T extends { a: string, readonly b: number }>(obj: T): T;
    declare function f14<const T extends Record<string, unknown>>(obj: T): T;
    declare function f15<const T extends Readonly<Record<string, unknown>>>(obj: T): T;
    
    f10({ a: "hello", b: 42 });  // { a: string; b: number; }
    f11({ a: "hello", b: 42 });  // { readonly a: "hello"; readonly b: 42; }
    f12({ a: "hello", b: 42 });  // { a: "hello"; b: 42; }
    f13({ a: "hello", b: 42 });  // { a: "hello"; readonly b: 42; }
    f14({ a: "hello", b: 42 });  // { a: "hello"; b: 42; }
    f15({ a: "hello", b: 42 });  // { readonly a: "hello"; readonly b: 42; }
    
    // https://github.com/microsoft/TypeScript/issues/13347
    
    interface MutableValue<T> {
        value: T;
    }
    
    interface ImmutableValue<T> {
        readonly value: T;
    }
    
    let i: ImmutableValue<string> = { value: "hi" };
    i.value = "Excellent, I can't change it";  // Error
      ~~~~~
!!! error TS2540: Cannot assign to 'value' because it is a read-only property.
    
    let m: MutableValue<string> = i;  // Error
        ~
!!! error TS2322: Type 'ImmutableValue<string>' is not assignable to type 'MutableValue<string>'.
!!! error TS2322:   Property 'value' is 'readonly' in the source but not in the target.
    m.value = "Oh dear, I can change it";
    