File: unionPropertyOfProtectedAndIntersectionProperty.errors.txt

package info (click to toggle)
node-typescript 5.0.4%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 459,116 kB
  • sloc: javascript: 1,972,754; makefile: 6; sh: 1
file content (42 lines) | stat: -rw-r--r-- 2,075 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
tests/cases/compiler/unionPropertyOfProtectedAndIntersectionProperty.ts(19,23): error TS2339: Property 'foo' does not exist on type 'Foo | Bar'.


==== tests/cases/compiler/unionPropertyOfProtectedAndIntersectionProperty.ts (1 errors) ====
    class Foo {
      protected foo = 0;
    }
    
    class Bar {
      protected foo = 0;
    }
    
    type Nothing<V extends Foo> = void;
    
    type Broken<V extends Array<Foo | Bar>> = {
      readonly [P in keyof V]: V[P] extends Foo ? Nothing<V[P]> : never;
    };
    
    // The issue above, #49517, is fixed very indirectly. Here's some code
    // that shows the direct result of the change:
    
    type _3 = (Foo & Bar)['foo'];         // Ok
    type _4 = (Foo | Bar)['foo'];         // Error
                          ~~~~~
!!! error TS2339: Property 'foo' does not exist on type 'Foo | Bar'.
    type _5 = (Foo | (Foo & Bar))['foo']; // Prev error, now ok
    
    // V[P] in `Nothing<V[P]>` is the substitution type `V[P] & Foo`. When
    // checking if that's assignable to `Foo` in the constraint of `Nothing`,
    // it passes the regular assignability check but then goes into intersection
    // property checks. To pull `foo` from the substitution type, it gets the
    // apparent type, which turns out to be something like `(Foo & Foo') | (Foo & Bar)`
    // where `Foo` and `Foo'` are different this-type instantiations of `Foo`.
    // Those two instantiations have the same `foo` property, but then `(Foo & Bar)['foo']`
    // is a synthesized intersection property with a declaration in `Foo` and a
    // declaration in `Bar`. Because the former was marked as protected and the
    // latter was a different symbol, we previously thought the two symbols were
    // totally unrelated, as in `(Foo | Bar)['foo']`. The fix I implemented is to
    // check not that the two property symbols are identical, but that they share
    // some common declaration. The change is directly observable by seeing whether
    // `(Foo | (Foo & Bar))['foo']` is allowed.