mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Remove assignability cases in getNarrowedType + an isArray improvement for readonly arrays (#39258)
* Explore using a different isArray declaration * Add tests and the new isArray definition * Baseline updates * Upda the isArray type
This commit is contained in:
@@ -21984,15 +21984,11 @@ namespace ts {
|
||||
return assignableType;
|
||||
}
|
||||
}
|
||||
// If the candidate type is a subtype of the target type, narrow to the candidate type.
|
||||
// Otherwise, if the target type is assignable to the candidate type, keep the target type.
|
||||
// Otherwise, if the candidate type is assignable to the target type, narrow to the candidate
|
||||
// type. Otherwise, the types are completely unrelated, so narrow to an intersection of the
|
||||
// two types.
|
||||
return isTypeSubtypeOf(candidate, type) ? candidate :
|
||||
isTypeAssignableTo(type, candidate) ? type :
|
||||
isTypeAssignableTo(candidate, type) ? candidate :
|
||||
getIntersectionType([type, candidate]);
|
||||
|
||||
// If the candidate type is a subtype of the target type, narrow to the candidate type,
|
||||
// if the target type is a subtype of the candidate type, narrow to the target type,
|
||||
// otherwise, narrow to an intersection of the two types.
|
||||
return isTypeSubtypeOf(candidate, type) ? candidate : isTypeSubtypeOf(type, candidate) ? type : getIntersectionType([type, candidate]);
|
||||
}
|
||||
|
||||
function narrowTypeByCallExpression(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
|
||||
|
||||
2
src/lib/es5.d.ts
vendored
2
src/lib/es5.d.ts
vendored
@@ -1376,7 +1376,7 @@ interface ArrayConstructor {
|
||||
(arrayLength?: number): any[];
|
||||
<T>(arrayLength: number): T[];
|
||||
<T>(...items: T[]): T[];
|
||||
isArray(arg: any): arg is any[];
|
||||
isArray<T>(arg: T | {}): arg is T extends readonly any[] ? (unknown extends T ? never : readonly any[]) : any[];
|
||||
readonly prototype: any[];
|
||||
}
|
||||
|
||||
|
||||
100
tests/baselines/reference/consistentUnionSubtypeReduction.js
Normal file
100
tests/baselines/reference/consistentUnionSubtypeReduction.js
Normal file
@@ -0,0 +1,100 @@
|
||||
//// [consistentUnionSubtypeReduction.ts]
|
||||
// https://github.com/microsoft/TypeScript/issues/31155
|
||||
|
||||
declare const MyArray: {
|
||||
isArray<T>(arg: T | {}): arg is T extends readonly any[] ? (unknown extends T ? never : readonly any[]) : any[];
|
||||
};
|
||||
|
||||
declare const a: readonly string[] | string;
|
||||
declare const b: string[] | string;
|
||||
declare const c: unknown;
|
||||
|
||||
if (MyArray.isArray(a)) {
|
||||
a; // readonly string[]
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
}
|
||||
a; // readonly string[] | string;
|
||||
|
||||
if (MyArray.isArray(b)) {
|
||||
b; // string[] | string;
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
}
|
||||
b; // string[] | string;
|
||||
|
||||
if (MyArray.isArray(c)) {
|
||||
c; // any[]
|
||||
}
|
||||
|
||||
|
||||
function f<T>(x: T) {
|
||||
const a: readonly T[] | string = null!;
|
||||
const b: T[] | string = null!;
|
||||
const c: T = null!;
|
||||
|
||||
if (MyArray.isArray(a)) {
|
||||
a; // readonly T[]
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
}
|
||||
a; // readonly T[] | string;
|
||||
|
||||
if (MyArray.isArray(b)) {
|
||||
b; // T[]
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
}
|
||||
b;
|
||||
|
||||
if (MyArray.isArray(c)) {
|
||||
c; // T & (T extends readonly any[] ? readonly any[] : any[])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [consistentUnionSubtypeReduction.js]
|
||||
// https://github.com/microsoft/TypeScript/issues/31155
|
||||
if (MyArray.isArray(a)) {
|
||||
a; // readonly string[]
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
}
|
||||
a; // readonly string[] | string;
|
||||
if (MyArray.isArray(b)) {
|
||||
b; // string[] | string;
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
}
|
||||
b; // string[] | string;
|
||||
if (MyArray.isArray(c)) {
|
||||
c; // any[]
|
||||
}
|
||||
function f(x) {
|
||||
var a = null;
|
||||
var b = null;
|
||||
var c = null;
|
||||
if (MyArray.isArray(a)) {
|
||||
a; // readonly T[]
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
}
|
||||
a; // readonly T[] | string;
|
||||
if (MyArray.isArray(b)) {
|
||||
b; // T[]
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
}
|
||||
b;
|
||||
if (MyArray.isArray(c)) {
|
||||
c; // T & (T extends readonly any[] ? readonly any[] : any[])
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
=== tests/cases/compiler/consistentUnionSubtypeReduction.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/31155
|
||||
|
||||
declare const MyArray: {
|
||||
>MyArray : Symbol(MyArray, Decl(consistentUnionSubtypeReduction.ts, 2, 13))
|
||||
|
||||
isArray<T>(arg: T | {}): arg is T extends readonly any[] ? (unknown extends T ? never : readonly any[]) : any[];
|
||||
>isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>T : Symbol(T, Decl(consistentUnionSubtypeReduction.ts, 3, 12))
|
||||
>arg : Symbol(arg, Decl(consistentUnionSubtypeReduction.ts, 3, 15))
|
||||
>T : Symbol(T, Decl(consistentUnionSubtypeReduction.ts, 3, 12))
|
||||
>arg : Symbol(arg, Decl(consistentUnionSubtypeReduction.ts, 3, 15))
|
||||
>T : Symbol(T, Decl(consistentUnionSubtypeReduction.ts, 3, 12))
|
||||
>T : Symbol(T, Decl(consistentUnionSubtypeReduction.ts, 3, 12))
|
||||
|
||||
};
|
||||
|
||||
declare const a: readonly string[] | string;
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 6, 13))
|
||||
|
||||
declare const b: string[] | string;
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 7, 13))
|
||||
|
||||
declare const c: unknown;
|
||||
>c : Symbol(c, Decl(consistentUnionSubtypeReduction.ts, 8, 13))
|
||||
|
||||
if (MyArray.isArray(a)) {
|
||||
>MyArray.isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>MyArray : Symbol(MyArray, Decl(consistentUnionSubtypeReduction.ts, 2, 13))
|
||||
>isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 6, 13))
|
||||
|
||||
a; // readonly string[]
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 6, 13))
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 6, 13))
|
||||
}
|
||||
a; // readonly string[] | string;
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 6, 13))
|
||||
|
||||
if (MyArray.isArray(b)) {
|
||||
>MyArray.isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>MyArray : Symbol(MyArray, Decl(consistentUnionSubtypeReduction.ts, 2, 13))
|
||||
>isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 7, 13))
|
||||
|
||||
b; // string[] | string;
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 7, 13))
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 7, 13))
|
||||
}
|
||||
b; // string[] | string;
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 7, 13))
|
||||
|
||||
if (MyArray.isArray(c)) {
|
||||
>MyArray.isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>MyArray : Symbol(MyArray, Decl(consistentUnionSubtypeReduction.ts, 2, 13))
|
||||
>isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>c : Symbol(c, Decl(consistentUnionSubtypeReduction.ts, 8, 13))
|
||||
|
||||
c; // any[]
|
||||
>c : Symbol(c, Decl(consistentUnionSubtypeReduction.ts, 8, 13))
|
||||
}
|
||||
|
||||
|
||||
function f<T>(x: T) {
|
||||
>f : Symbol(f, Decl(consistentUnionSubtypeReduction.ts, 28, 1))
|
||||
>T : Symbol(T, Decl(consistentUnionSubtypeReduction.ts, 31, 11))
|
||||
>x : Symbol(x, Decl(consistentUnionSubtypeReduction.ts, 31, 14))
|
||||
>T : Symbol(T, Decl(consistentUnionSubtypeReduction.ts, 31, 11))
|
||||
|
||||
const a: readonly T[] | string = null!;
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 32, 9))
|
||||
>T : Symbol(T, Decl(consistentUnionSubtypeReduction.ts, 31, 11))
|
||||
|
||||
const b: T[] | string = null!;
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 33, 9))
|
||||
>T : Symbol(T, Decl(consistentUnionSubtypeReduction.ts, 31, 11))
|
||||
|
||||
const c: T = null!;
|
||||
>c : Symbol(c, Decl(consistentUnionSubtypeReduction.ts, 34, 9))
|
||||
>T : Symbol(T, Decl(consistentUnionSubtypeReduction.ts, 31, 11))
|
||||
|
||||
if (MyArray.isArray(a)) {
|
||||
>MyArray.isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>MyArray : Symbol(MyArray, Decl(consistentUnionSubtypeReduction.ts, 2, 13))
|
||||
>isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 32, 9))
|
||||
|
||||
a; // readonly T[]
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 32, 9))
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 32, 9))
|
||||
}
|
||||
a; // readonly T[] | string;
|
||||
>a : Symbol(a, Decl(consistentUnionSubtypeReduction.ts, 32, 9))
|
||||
|
||||
if (MyArray.isArray(b)) {
|
||||
>MyArray.isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>MyArray : Symbol(MyArray, Decl(consistentUnionSubtypeReduction.ts, 2, 13))
|
||||
>isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 33, 9))
|
||||
|
||||
b; // T[]
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 33, 9))
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 33, 9))
|
||||
}
|
||||
b;
|
||||
>b : Symbol(b, Decl(consistentUnionSubtypeReduction.ts, 33, 9))
|
||||
|
||||
if (MyArray.isArray(c)) {
|
||||
>MyArray.isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>MyArray : Symbol(MyArray, Decl(consistentUnionSubtypeReduction.ts, 2, 13))
|
||||
>isArray : Symbol(isArray, Decl(consistentUnionSubtypeReduction.ts, 2, 24))
|
||||
>c : Symbol(c, Decl(consistentUnionSubtypeReduction.ts, 34, 9))
|
||||
|
||||
c; // T & (T extends readonly any[] ? readonly any[] : any[])
|
||||
>c : Symbol(c, Decl(consistentUnionSubtypeReduction.ts, 34, 9))
|
||||
}
|
||||
}
|
||||
|
||||
132
tests/baselines/reference/consistentUnionSubtypeReduction.types
Normal file
132
tests/baselines/reference/consistentUnionSubtypeReduction.types
Normal file
@@ -0,0 +1,132 @@
|
||||
=== tests/cases/compiler/consistentUnionSubtypeReduction.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/31155
|
||||
|
||||
declare const MyArray: {
|
||||
>MyArray : { isArray<T>(arg: {} | T): arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]; }
|
||||
|
||||
isArray<T>(arg: T | {}): arg is T extends readonly any[] ? (unknown extends T ? never : readonly any[]) : any[];
|
||||
>isArray : <T>(arg: T | {}) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>arg : {} | T
|
||||
|
||||
};
|
||||
|
||||
declare const a: readonly string[] | string;
|
||||
>a : string | readonly string[]
|
||||
|
||||
declare const b: string[] | string;
|
||||
>b : string | string[]
|
||||
|
||||
declare const c: unknown;
|
||||
>c : unknown
|
||||
|
||||
if (MyArray.isArray(a)) {
|
||||
>MyArray.isArray(a) : boolean
|
||||
>MyArray.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>MyArray : { isArray<T>(arg: {} | T): arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]; }
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>a : string | readonly string[]
|
||||
|
||||
a; // readonly string[]
|
||||
>a : readonly string[]
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
>a : string
|
||||
}
|
||||
a; // readonly string[] | string;
|
||||
>a : string | readonly string[]
|
||||
|
||||
if (MyArray.isArray(b)) {
|
||||
>MyArray.isArray(b) : boolean
|
||||
>MyArray.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>MyArray : { isArray<T>(arg: {} | T): arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]; }
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>b : string | string[]
|
||||
|
||||
b; // string[] | string;
|
||||
>b : string[]
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
>b : string
|
||||
}
|
||||
b; // string[] | string;
|
||||
>b : string | string[]
|
||||
|
||||
if (MyArray.isArray(c)) {
|
||||
>MyArray.isArray(c) : boolean
|
||||
>MyArray.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>MyArray : { isArray<T>(arg: {} | T): arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]; }
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>c : unknown
|
||||
|
||||
c; // any[]
|
||||
>c : any[]
|
||||
}
|
||||
|
||||
|
||||
function f<T>(x: T) {
|
||||
>f : <T>(x: T) => void
|
||||
>x : T
|
||||
|
||||
const a: readonly T[] | string = null!;
|
||||
>a : string | readonly T[]
|
||||
>null! : null
|
||||
>null : null
|
||||
|
||||
const b: T[] | string = null!;
|
||||
>b : string | T[]
|
||||
>null! : null
|
||||
>null : null
|
||||
|
||||
const c: T = null!;
|
||||
>c : T
|
||||
>null! : null
|
||||
>null : null
|
||||
|
||||
if (MyArray.isArray(a)) {
|
||||
>MyArray.isArray(a) : boolean
|
||||
>MyArray.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>MyArray : { isArray<T>(arg: {} | T): arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]; }
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>a : string | readonly T[]
|
||||
|
||||
a; // readonly T[]
|
||||
>a : readonly T[]
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
>a : string
|
||||
}
|
||||
a; // readonly T[] | string;
|
||||
>a : string | readonly T[]
|
||||
|
||||
if (MyArray.isArray(b)) {
|
||||
>MyArray.isArray(b) : boolean
|
||||
>MyArray.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>MyArray : { isArray<T>(arg: {} | T): arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]; }
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>b : string | T[]
|
||||
|
||||
b; // T[]
|
||||
>b : T[]
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
>b : string
|
||||
}
|
||||
b;
|
||||
>b : string | T[]
|
||||
|
||||
if (MyArray.isArray(c)) {
|
||||
>MyArray.isArray(c) : boolean
|
||||
>MyArray.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>MyArray : { isArray<T>(arg: {} | T): arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]; }
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>c : T
|
||||
|
||||
c; // T & (T extends readonly any[] ? readonly any[] : any[])
|
||||
>c : T & (T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,9 +67,9 @@ export const updateIfChanged = <T>(t: T) => {
|
||||
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
|
||||
>Array.isArray(u) ? [] : {} : undefined[] | {}
|
||||
>Array.isArray(u) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>u : U
|
||||
>[] : undefined[]
|
||||
>{} : {}
|
||||
|
||||
@@ -1109,9 +1109,9 @@ define(function () {
|
||||
>Array : ArrayConstructor
|
||||
|
||||
Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; };
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>function (value) { return Object.prototype.toString.call(value) === '[object Array]'; } : (value: any) => boolean
|
||||
>value : any
|
||||
>Object.prototype.toString.call(value) === '[object Array]' : boolean
|
||||
|
||||
@@ -70,8 +70,8 @@ function fn2(x: Base) {
|
||||
// 1.5: y: Base
|
||||
// Want: y: Derived1
|
||||
let y = x;
|
||||
>y : Derived1
|
||||
>x : Derived1
|
||||
>y : Base & Derived1
|
||||
>x : Base & Derived1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@ function fn4(x: Base|Derived2) {
|
||||
// 1.5: y: {}
|
||||
// Want: Derived1
|
||||
let y = x;
|
||||
>y : Derived1
|
||||
>x : Derived1
|
||||
>y : (Base & Derived1) | (Derived2 & Derived1)
|
||||
>x : (Base & Derived1) | (Derived2 & Derived1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ var maybeArray: number | number[];
|
||||
|
||||
if (Array.isArray(maybeArray)) {
|
||||
>Array.isArray(maybeArray) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>maybeArray : number | number[]
|
||||
|
||||
maybeArray.length; // OK
|
||||
|
||||
@@ -66,9 +66,9 @@ function f2() {
|
||||
>a4 : string | false | (string | false)[]
|
||||
>Array.isArray(elOrA) ? elOrA : [elOrA] : (string | false)[]
|
||||
>Array.isArray(elOrA) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>elOrA : string | false | (string | false)[]
|
||||
>elOrA : (string | false)[]
|
||||
>[elOrA] : (string | false)[]
|
||||
@@ -83,9 +83,9 @@ function f2() {
|
||||
>...Array.isArray(elOrA) ? elOrA : [elOrA] : string | false
|
||||
>Array.isArray(elOrA) ? elOrA : [elOrA] : (string | false)[]
|
||||
>Array.isArray(elOrA) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>elOrA : string | false | (string | false)[]
|
||||
>elOrA : (string | false)[]
|
||||
>[elOrA] : (string | false)[]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
var isArray = Array.isArray;
|
||||
>isArray : Function
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ export function doRemove(dds: F | F[]) {
|
||||
if (!Array.isArray(dds)) {
|
||||
>!Array.isArray(dds) : boolean
|
||||
>Array.isArray(dds) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>dds : F | F[]
|
||||
|
||||
dds = [dds]
|
||||
|
||||
@@ -3068,13 +3068,13 @@ module Harness {
|
||||
>(Array.isArray && Array.isArray(arg)) || arg instanceof Array : boolean
|
||||
>(Array.isArray && Array.isArray(arg)) : boolean
|
||||
>Array.isArray && Array.isArray(arg) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array.isArray(arg) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>arg : any
|
||||
>arg instanceof Array : boolean
|
||||
>arg : any
|
||||
|
||||
@@ -77,9 +77,9 @@ function isShape(s : Shapes): s is Shape {
|
||||
return !Array.isArray(s);
|
||||
>!Array.isArray(s) : boolean
|
||||
>Array.isArray(s) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>s : Shapes
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]];
|
||||
>...Array.isArray(foo2) ? foo2 : [foo2] : FooBase
|
||||
>Array.isArray(foo2) ? foo2 : [foo2] : FooArray
|
||||
>Array.isArray(foo2) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array.isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>isArray : <T>(arg: {} | T) => arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[]
|
||||
>foo2 : Foo
|
||||
>foo2 : FooArray
|
||||
>[foo2] : FooBase[]
|
||||
|
||||
@@ -176,17 +176,17 @@ function identifyBeast(beast: Beast) {
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
|
||||
if (beast.legs === 4) {
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast.legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
|
||||
log(`pegasus - 4 legs, wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 48, 1))
|
||||
}
|
||||
else if (beast.legs === 2) {
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast.legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
|
||||
log(`bird - 2 legs, wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 48, 1))
|
||||
@@ -194,9 +194,9 @@ function identifyBeast(beast: Beast) {
|
||||
else {
|
||||
log(`unknown - ${beast.legs} legs, wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 48, 1))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast.legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,9 +204,9 @@ function identifyBeast(beast: Beast) {
|
||||
else {
|
||||
log(`manbearpig - ${beast.legs} legs, no wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 48, 1))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast.legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -166,12 +166,12 @@ function identifyBeast(beast: Beast) {
|
||||
if (hasWings(beast)) {
|
||||
>hasWings(beast) : boolean
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>beast : Legged
|
||||
>beast : Beast & Legged
|
||||
|
||||
if (beast.legs === 4) {
|
||||
>beast.legs === 4 : boolean
|
||||
>beast.legs : number
|
||||
>beast : Legged & Winged
|
||||
>beast : Beast & Legged & Winged
|
||||
>legs : number
|
||||
>4 : 4
|
||||
|
||||
@@ -183,7 +183,7 @@ function identifyBeast(beast: Beast) {
|
||||
else if (beast.legs === 2) {
|
||||
>beast.legs === 2 : boolean
|
||||
>beast.legs : number
|
||||
>beast : Legged & Winged
|
||||
>beast : Beast & Legged & Winged
|
||||
>legs : number
|
||||
>2 : 2
|
||||
|
||||
@@ -198,7 +198,7 @@ function identifyBeast(beast: Beast) {
|
||||
>log : (s: string) => void
|
||||
>`unknown - ${beast.legs} legs, wings` : string
|
||||
>beast.legs : number
|
||||
>beast : Legged & Winged
|
||||
>beast : Beast & Legged & Winged
|
||||
>legs : number
|
||||
}
|
||||
}
|
||||
@@ -210,7 +210,7 @@ function identifyBeast(beast: Beast) {
|
||||
>log : (s: string) => void
|
||||
>`manbearpig - ${beast.legs} legs, no wings` : string
|
||||
>beast.legs : number
|
||||
>beast : Legged
|
||||
>beast : Beast & Legged
|
||||
>legs : number
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20)
|
||||
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (1 errors) ====
|
||||
interface I { global: string; }
|
||||
var result: I;
|
||||
var result2: I;
|
||||
var result!: I;
|
||||
var result2!: I;
|
||||
|
||||
if (!(result instanceof RegExp)) {
|
||||
result = result2;
|
||||
@@ -13,4 +13,32 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20)
|
||||
~~~~~~
|
||||
!!! error TS2339: Property 'global' does not exist on type 'never'.
|
||||
!!! error TS2339: The intersection 'I & RegExp' was reduced to 'never' because property 'global' has conflicting types in some constituents.
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #31155
|
||||
|
||||
interface OnChanges {
|
||||
onChanges(changes: Record<string, unknown>): void
|
||||
}
|
||||
interface Validator {
|
||||
validate(): null | Record<string, unknown>;
|
||||
}
|
||||
|
||||
class C {
|
||||
validate() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
let v: Validator & Partial<OnChanges> = null as any;
|
||||
if (v instanceof C) {
|
||||
v // Validator & Partial<OnChanges> & C
|
||||
}
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
if (v.onChanges) {
|
||||
v.onChanges({});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,40 @@
|
||||
//// [typeGuardsWithInstanceOf.ts]
|
||||
interface I { global: string; }
|
||||
var result: I;
|
||||
var result2: I;
|
||||
var result!: I;
|
||||
var result2!: I;
|
||||
|
||||
if (!(result instanceof RegExp)) {
|
||||
result = result2;
|
||||
} else if (!result.global) {
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #31155
|
||||
|
||||
interface OnChanges {
|
||||
onChanges(changes: Record<string, unknown>): void
|
||||
}
|
||||
interface Validator {
|
||||
validate(): null | Record<string, unknown>;
|
||||
}
|
||||
|
||||
class C {
|
||||
validate() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
let v: Validator & Partial<OnChanges> = null as any;
|
||||
if (v instanceof C) {
|
||||
v // Validator & Partial<OnChanges> & C
|
||||
}
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
if (v.onChanges) {
|
||||
v.onChanges({});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//// [typeGuardsWithInstanceOf.js]
|
||||
var result;
|
||||
@@ -16,3 +44,21 @@ if (!(result instanceof RegExp)) {
|
||||
}
|
||||
else if (!result.global) {
|
||||
}
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
}
|
||||
C.prototype.validate = function () {
|
||||
return {};
|
||||
};
|
||||
return C;
|
||||
}());
|
||||
function foo() {
|
||||
var v = null;
|
||||
if (v instanceof C) {
|
||||
v; // Validator & Partial<OnChanges> & C
|
||||
}
|
||||
v; // Validator & Partial<OnChanges> via subtype reduction
|
||||
if (v.onChanges) {
|
||||
v.onChanges({});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ interface I { global: string; }
|
||||
>I : Symbol(I, Decl(typeGuardsWithInstanceOf.ts, 0, 0))
|
||||
>global : Symbol(I.global, Decl(typeGuardsWithInstanceOf.ts, 0, 13))
|
||||
|
||||
var result: I;
|
||||
var result!: I;
|
||||
>result : Symbol(result, Decl(typeGuardsWithInstanceOf.ts, 1, 3))
|
||||
>I : Symbol(I, Decl(typeGuardsWithInstanceOf.ts, 0, 0))
|
||||
|
||||
var result2: I;
|
||||
var result2!: I;
|
||||
>result2 : Symbol(result2, Decl(typeGuardsWithInstanceOf.ts, 2, 3))
|
||||
>I : Symbol(I, Decl(typeGuardsWithInstanceOf.ts, 0, 0))
|
||||
|
||||
@@ -22,3 +22,64 @@ if (!(result instanceof RegExp)) {
|
||||
} else if (!result.global) {
|
||||
>result : Symbol(result, Decl(typeGuardsWithInstanceOf.ts, 1, 3))
|
||||
}
|
||||
|
||||
// Repro from #31155
|
||||
|
||||
interface OnChanges {
|
||||
>OnChanges : Symbol(OnChanges, Decl(typeGuardsWithInstanceOf.ts, 7, 1))
|
||||
|
||||
onChanges(changes: Record<string, unknown>): void
|
||||
>onChanges : Symbol(OnChanges.onChanges, Decl(typeGuardsWithInstanceOf.ts, 11, 21))
|
||||
>changes : Symbol(changes, Decl(typeGuardsWithInstanceOf.ts, 12, 14))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
interface Validator {
|
||||
>Validator : Symbol(Validator, Decl(typeGuardsWithInstanceOf.ts, 13, 1))
|
||||
|
||||
validate(): null | Record<string, unknown>;
|
||||
>validate : Symbol(Validator.validate, Decl(typeGuardsWithInstanceOf.ts, 14, 21))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
|
||||
class C {
|
||||
>C : Symbol(C, Decl(typeGuardsWithInstanceOf.ts, 16, 1))
|
||||
|
||||
validate() {
|
||||
>validate : Symbol(C.validate, Decl(typeGuardsWithInstanceOf.ts, 18, 9))
|
||||
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
>foo : Symbol(foo, Decl(typeGuardsWithInstanceOf.ts, 22, 1))
|
||||
|
||||
let v: Validator & Partial<OnChanges> = null as any;
|
||||
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
|
||||
>Validator : Symbol(Validator, Decl(typeGuardsWithInstanceOf.ts, 13, 1))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>OnChanges : Symbol(OnChanges, Decl(typeGuardsWithInstanceOf.ts, 7, 1))
|
||||
|
||||
if (v instanceof C) {
|
||||
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
|
||||
>C : Symbol(C, Decl(typeGuardsWithInstanceOf.ts, 16, 1))
|
||||
|
||||
v // Validator & Partial<OnChanges> & C
|
||||
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
|
||||
}
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
|
||||
|
||||
if (v.onChanges) {
|
||||
>v.onChanges : Symbol(onChanges, Decl(typeGuardsWithInstanceOf.ts, 11, 21))
|
||||
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
|
||||
>onChanges : Symbol(onChanges, Decl(typeGuardsWithInstanceOf.ts, 11, 21))
|
||||
|
||||
v.onChanges({});
|
||||
>v.onChanges : Symbol(onChanges, Decl(typeGuardsWithInstanceOf.ts, 11, 21))
|
||||
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
|
||||
>onChanges : Symbol(onChanges, Decl(typeGuardsWithInstanceOf.ts, 11, 21))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
interface I { global: string; }
|
||||
>global : string
|
||||
|
||||
var result: I;
|
||||
var result!: I;
|
||||
>result : I
|
||||
|
||||
var result2: I;
|
||||
var result2!: I;
|
||||
>result2 : I
|
||||
|
||||
if (!(result instanceof RegExp)) {
|
||||
@@ -26,3 +26,62 @@ if (!(result instanceof RegExp)) {
|
||||
>result : never
|
||||
>global : any
|
||||
}
|
||||
|
||||
// Repro from #31155
|
||||
|
||||
interface OnChanges {
|
||||
onChanges(changes: Record<string, unknown>): void
|
||||
>onChanges : (changes: Record<string, unknown>) => void
|
||||
>changes : Record<string, unknown>
|
||||
}
|
||||
interface Validator {
|
||||
validate(): null | Record<string, unknown>;
|
||||
>validate : () => null | Record<string, unknown>
|
||||
>null : null
|
||||
}
|
||||
|
||||
class C {
|
||||
>C : C
|
||||
|
||||
validate() {
|
||||
>validate : () => {}
|
||||
|
||||
return {}
|
||||
>{} : {}
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
>foo : () => void
|
||||
|
||||
let v: Validator & Partial<OnChanges> = null as any;
|
||||
>v : Validator & Partial<OnChanges>
|
||||
>null as any : any
|
||||
>null : null
|
||||
|
||||
if (v instanceof C) {
|
||||
>v instanceof C : boolean
|
||||
>v : Validator & Partial<OnChanges>
|
||||
>C : typeof C
|
||||
|
||||
v // Validator & Partial<OnChanges> & C
|
||||
>v : Validator & Partial<OnChanges> & C
|
||||
}
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
>v : Validator & Partial<OnChanges>
|
||||
|
||||
if (v.onChanges) {
|
||||
>v.onChanges : ((changes: Record<string, unknown>) => void) | undefined
|
||||
>v : Validator & Partial<OnChanges>
|
||||
>onChanges : ((changes: Record<string, unknown>) => void) | undefined
|
||||
|
||||
v.onChanges({});
|
||||
>v.onChanges({}) : void
|
||||
>v.onChanges : (changes: Record<string, unknown>) => void
|
||||
>v : Validator & Partial<OnChanges>
|
||||
>onChanges : (changes: Record<string, unknown>) => void
|
||||
>{} : {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
56
tests/cases/compiler/consistentUnionSubtypeReduction.ts
Normal file
56
tests/cases/compiler/consistentUnionSubtypeReduction.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
// https://github.com/microsoft/TypeScript/issues/31155
|
||||
|
||||
declare const MyArray: {
|
||||
isArray<T>(arg: T | {}): arg is T extends readonly any[] ? (unknown extends T ? never : readonly any[]) : any[];
|
||||
};
|
||||
|
||||
declare const a: readonly string[] | string;
|
||||
declare const b: string[] | string;
|
||||
declare const c: unknown;
|
||||
|
||||
if (MyArray.isArray(a)) {
|
||||
a; // readonly string[]
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
}
|
||||
a; // readonly string[] | string;
|
||||
|
||||
if (MyArray.isArray(b)) {
|
||||
b; // string[] | string;
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
}
|
||||
b; // string[] | string;
|
||||
|
||||
if (MyArray.isArray(c)) {
|
||||
c; // any[]
|
||||
}
|
||||
|
||||
|
||||
function f<T>(x: T) {
|
||||
const a: readonly T[] | string = null!;
|
||||
const b: T[] | string = null!;
|
||||
const c: T = null!;
|
||||
|
||||
if (MyArray.isArray(a)) {
|
||||
a; // readonly T[]
|
||||
}
|
||||
else {
|
||||
a; // string
|
||||
}
|
||||
a; // readonly T[] | string;
|
||||
|
||||
if (MyArray.isArray(b)) {
|
||||
b; // T[]
|
||||
}
|
||||
else {
|
||||
b; // string
|
||||
}
|
||||
b;
|
||||
|
||||
if (MyArray.isArray(c)) {
|
||||
c; // T & (T extends readonly any[] ? readonly any[] : any[])
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,37 @@
|
||||
interface I { global: string; }
|
||||
var result: I;
|
||||
var result2: I;
|
||||
// @strictNullChecks: true
|
||||
|
||||
interface I { global: string; }
|
||||
var result!: I;
|
||||
var result2!: I;
|
||||
|
||||
if (!(result instanceof RegExp)) {
|
||||
result = result2;
|
||||
} else if (!result.global) {
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #31155
|
||||
|
||||
interface OnChanges {
|
||||
onChanges(changes: Record<string, unknown>): void
|
||||
}
|
||||
interface Validator {
|
||||
validate(): null | Record<string, unknown>;
|
||||
}
|
||||
|
||||
class C {
|
||||
validate() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
let v: Validator & Partial<OnChanges> = null as any;
|
||||
if (v instanceof C) {
|
||||
v // Validator & Partial<OnChanges> & C
|
||||
}
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
if (v.onChanges) {
|
||||
v.onChanges({});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user