Skip to content

Commit f6b438b

Browse files
committed
A second attempt at readonly array support persisting through isArray
1 parent a894f8a commit f6b438b

8 files changed

+48
-37
lines changed

lib/lib.es5.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1408,7 +1408,7 @@ interface ArrayConstructor {
14081408
(arrayLength?: number): any[];
14091409
<T>(arrayLength: number): T[];
14101410
<T>(...items: T[]): T[];
1411-
isArray(arg: any): arg is any[];
1411+
isArray(arg: any): arg is readonly unknown[];
14121412
readonly prototype: any[];
14131413
}
14141414

src/compiler/checker.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22999,11 +22999,16 @@ namespace ts {
2299922999
}
2300023000
}
2300123001

23002-
// If the candidate type is a subtype of the target type, narrow to the candidate type,
23003-
// if the target type is a subtype of the candidate type, narrow to the target type,
23004-
// otherwise, narrow to an intersection of the two types.
23005-
return isTypeSubtypeOf(candidate, type) ? candidate : isTypeSubtypeOf(type, candidate) ? type : getIntersectionType([type, candidate]);
23006-
}
23002+
// If the candidate type is a subtype of the target type, narrow to the candidate type.
23003+
// Otherwise, if the target type is assignable to the candidate type, keep the target type.
23004+
// Otherwise, if the candidate type is assignable to the target type, narrow to the candidate
23005+
// type. Otherwise, the types are completely unrelated, so narrow to an intersection of the
23006+
// two types.
23007+
return isTypeSubtypeOf(candidate, type) ? candidate :
23008+
isTypeAssignableTo(type, candidate) ? type :
23009+
isTypeAssignableTo(candidate, type) ? candidate :
23010+
getIntersectionType([type, candidate]);
23011+
}
2300723012

2300823013
function narrowTypeByCallExpression(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
2300923014
if (hasMatchingArgument(callExpression, reference)) {

tests/baselines/reference/instanceOfAssignability.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ function fn2(x: Base) {
7070
// 1.5: y: Base
7171
// Want: y: Derived1
7272
let y = x;
73-
>y : Base & Derived1
74-
>x : Base & Derived1
73+
>y : Derived1
74+
>x : Derived1
7575
}
7676
}
7777

@@ -104,8 +104,8 @@ function fn4(x: Base|Derived2) {
104104
// 1.5: y: {}
105105
// Want: Derived1
106106
let y = x;
107-
>y : (Base | Derived2) & Derived1
108-
>x : (Base | Derived2) & Derived1
107+
>y : Derived1
108+
>x : Derived1
109109
}
110110
}
111111

tests/baselines/reference/typeGuardIntersectionTypes.symbols

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -176,37 +176,37 @@ function identifyBeast(beast: Beast) {
176176
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
177177

178178
if (beast.legs === 4) {
179-
>beast.legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
179+
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
180180
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
181-
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
181+
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
182182

183183
log(`pegasus - 4 legs, wings`);
184184
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 48, 1))
185185
}
186186
else if (beast.legs === 2) {
187-
>beast.legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
187+
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
188188
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
189-
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
189+
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
190190

191191
log(`bird - 2 legs, wings`);
192192
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 48, 1))
193193
}
194194
else {
195195
log(`unknown - ${beast.legs} legs, wings`);
196196
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 48, 1))
197-
>beast.legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
197+
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
198198
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
199-
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
199+
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
200200
}
201201
}
202202

203203
// All non-winged beasts with legs
204204
else {
205205
log(`manbearpig - ${beast.legs} legs, no wings`);
206206
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 48, 1))
207-
>beast.legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
207+
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
208208
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
209-
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
209+
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
210210
}
211211
}
212212

tests/baselines/reference/typeGuardIntersectionTypes.types

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,12 @@ function identifyBeast(beast: Beast) {
166166
if (hasWings(beast)) {
167167
>hasWings(beast) : boolean
168168
>hasWings : (x: Beast) => x is Winged
169-
>beast : Beast & Legged
169+
>beast : Legged
170170

171171
if (beast.legs === 4) {
172172
>beast.legs === 4 : boolean
173173
>beast.legs : number
174-
>beast : Beast & Legged & Winged
174+
>beast : Legged & Winged
175175
>legs : number
176176
>4 : 4
177177

@@ -183,7 +183,7 @@ function identifyBeast(beast: Beast) {
183183
else if (beast.legs === 2) {
184184
>beast.legs === 2 : boolean
185185
>beast.legs : number
186-
>beast : Beast & Legged & Winged
186+
>beast : Legged & Winged
187187
>legs : number
188188
>2 : 2
189189

@@ -198,7 +198,7 @@ function identifyBeast(beast: Beast) {
198198
>log : (s: string) => void
199199
>`unknown - ${beast.legs} legs, wings` : `unknown - ${number} legs, wings`
200200
>beast.legs : number
201-
>beast : Beast & Legged & Winged
201+
>beast : Legged & Winged
202202
>legs : number
203203
}
204204
}
@@ -210,7 +210,7 @@ function identifyBeast(beast: Beast) {
210210
>log : (s: string) => void
211211
>`manbearpig - ${beast.legs} legs, no wings` : `manbearpig - ${number} legs, no wings`
212212
>beast.legs : number
213-
>beast : Beast & Legged
213+
>beast : Legged
214214
>legs : number
215215
}
216216
}

tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20): error TS2339: Property 'global' does not exist on type 'never'.
22
The intersection 'I & RegExp' was reduced to 'never' because property 'global' has conflicting types in some constituents.
3+
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(31,11): error TS2339: Property 'onChanges' does not exist on type 'C | (Validator & Partial<OnChanges>)'.
4+
Property 'onChanges' does not exist on type 'C'.
5+
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(32,11): error TS2339: Property 'onChanges' does not exist on type 'C | (Validator & Partial<OnChanges>)'.
6+
Property 'onChanges' does not exist on type 'C'.
37

48

5-
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (1 errors) ====
9+
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (3 errors) ====
610
interface I { global: string; }
711
var result!: I;
812
var result2!: I;
@@ -37,7 +41,13 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20)
3741
}
3842
v // Validator & Partial<OnChanges> via subtype reduction
3943
if (v.onChanges) {
44+
~~~~~~~~~
45+
!!! error TS2339: Property 'onChanges' does not exist on type 'C | (Validator & Partial<OnChanges>)'.
46+
!!! error TS2339: Property 'onChanges' does not exist on type 'C'.
4047
v.onChanges({});
48+
~~~~~~~~~
49+
!!! error TS2339: Property 'onChanges' does not exist on type 'C | (Validator & Partial<OnChanges>)'.
50+
!!! error TS2339: Property 'onChanges' does not exist on type 'C'.
4151
}
4252
}
4353

tests/baselines/reference/typeGuardsWithInstanceOf.symbols

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,10 @@ function foo() {
7171
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
7272

7373
if (v.onChanges) {
74-
>v.onChanges : Symbol(onChanges, Decl(typeGuardsWithInstanceOf.ts, 11, 21))
7574
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
76-
>onChanges : Symbol(onChanges, Decl(typeGuardsWithInstanceOf.ts, 11, 21))
7775

7876
v.onChanges({});
79-
>v.onChanges : Symbol(onChanges, Decl(typeGuardsWithInstanceOf.ts, 11, 21))
8077
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
81-
>onChanges : Symbol(onChanges, Decl(typeGuardsWithInstanceOf.ts, 11, 21))
8278
}
8379
}
8480

tests/baselines/reference/typeGuardsWithInstanceOf.types

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,21 @@ function foo() {
6565
>C : typeof C
6666

6767
v // Validator & Partial<OnChanges> & C
68-
>v : Validator & Partial<OnChanges> & C
68+
>v : C
6969
}
7070
v // Validator & Partial<OnChanges> via subtype reduction
71-
>v : Validator & Partial<OnChanges>
71+
>v : C | (Validator & Partial<OnChanges>)
7272

7373
if (v.onChanges) {
74-
>v.onChanges : ((changes: Record<string, unknown>) => void) | undefined
75-
>v : Validator & Partial<OnChanges>
76-
>onChanges : ((changes: Record<string, unknown>) => void) | undefined
74+
>v.onChanges : any
75+
>v : C | (Validator & Partial<OnChanges>)
76+
>onChanges : any
7777

7878
v.onChanges({});
79-
>v.onChanges({}) : void
80-
>v.onChanges : (changes: Record<string, unknown>) => void
81-
>v : Validator & Partial<OnChanges>
82-
>onChanges : (changes: Record<string, unknown>) => void
79+
>v.onChanges({}) : any
80+
>v.onChanges : any
81+
>v : C | (Validator & Partial<OnChanges>)
82+
>onChanges : any
8383
>{} : {}
8484
}
8585
}

0 commit comments

Comments
 (0)