mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Revert assignability cases in getNarrowedType (#42231)
* Revert subtype narrowing changes from readonly array PRs * Adds a test for the change * More baselines
This commit is contained in:
parent
1b19af0f14
commit
8c5fa5cc91
@ -23094,10 +23094,15 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// 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]);
|
||||
// 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]);
|
||||
}
|
||||
|
||||
function narrowTypeByCallExpression(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
|
||||
|
||||
@ -70,8 +70,8 @@ function fn2(x: Base) {
|
||||
// 1.5: y: Base
|
||||
// Want: y: Derived1
|
||||
let y = x;
|
||||
>y : Base & Derived1
|
||||
>x : Base & Derived1
|
||||
>y : Derived1
|
||||
>x : Derived1
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,8 +104,8 @@ function fn4(x: Base|Derived2) {
|
||||
// 1.5: y: {}
|
||||
// Want: Derived1
|
||||
let y = x;
|
||||
>y : (Base | Derived2) & Derived1
|
||||
>x : (Base | Derived2) & Derived1
|
||||
>y : Derived1
|
||||
>x : Derived1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
//// [narrowingAssignmentReadonlyRespectsAssertion.ts]
|
||||
// https://github.com/microsoft/TypeScript/issues/41984
|
||||
|
||||
interface TestCase<T extends string | number> {
|
||||
readonly val1: T | ReadonlyArray<T>;
|
||||
readonly val2: ReadonlyArray<T>;
|
||||
}
|
||||
|
||||
interface MultiCaseFixture<T> {
|
||||
cases: T[];
|
||||
}
|
||||
|
||||
function subDataFunc(): TestCase<string | number>[] {
|
||||
return [
|
||||
{ val1: "a", val2: ["a", "b", "c"] },
|
||||
{ val1: 2, val2: [1, 2, 3] },
|
||||
{ val1: ["a", "z"], val2: ["x", "y", "z"] },
|
||||
{ val1: [5, 10], val2: [10, 100, 1000] },
|
||||
];
|
||||
}
|
||||
|
||||
function dataFunc<T>(subFunc: () => T[]): MultiCaseFixture<T> {
|
||||
return { cases: subFunc() };
|
||||
}
|
||||
|
||||
function testFunc() {
|
||||
const fixture = dataFunc<TestCase<string | number>>(subDataFunc);
|
||||
fixture.cases.forEach(({ val1, val2 }) => {
|
||||
if (Array.isArray(val1)) {
|
||||
// This should retain val1 as being an array
|
||||
const reversedVal1 = val1.slice().reverse();
|
||||
console.log(reversedVal1);
|
||||
} else {
|
||||
console.log(val1);
|
||||
}
|
||||
console.log(val2);
|
||||
});
|
||||
}
|
||||
|
||||
testFunc();
|
||||
|
||||
|
||||
//// [narrowingAssignmentReadonlyRespectsAssertion.js]
|
||||
// https://github.com/microsoft/TypeScript/issues/41984
|
||||
function subDataFunc() {
|
||||
return [
|
||||
{ val1: "a", val2: ["a", "b", "c"] },
|
||||
{ val1: 2, val2: [1, 2, 3] },
|
||||
{ val1: ["a", "z"], val2: ["x", "y", "z"] },
|
||||
{ val1: [5, 10], val2: [10, 100, 1000] },
|
||||
];
|
||||
}
|
||||
function dataFunc(subFunc) {
|
||||
return { cases: subFunc() };
|
||||
}
|
||||
function testFunc() {
|
||||
var fixture = dataFunc(subDataFunc);
|
||||
fixture.cases.forEach(function (_a) {
|
||||
var val1 = _a.val1, val2 = _a.val2;
|
||||
if (Array.isArray(val1)) {
|
||||
// This should retain val1 as being an array
|
||||
var reversedVal1 = val1.slice().reverse();
|
||||
console.log(reversedVal1);
|
||||
}
|
||||
else {
|
||||
console.log(val1);
|
||||
}
|
||||
console.log(val2);
|
||||
});
|
||||
}
|
||||
testFunc();
|
||||
@ -0,0 +1,123 @@
|
||||
=== tests/cases/compiler/narrowingAssignmentReadonlyRespectsAssertion.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/41984
|
||||
|
||||
interface TestCase<T extends string | number> {
|
||||
>TestCase : Symbol(TestCase, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 19))
|
||||
|
||||
readonly val1: T | ReadonlyArray<T>;
|
||||
>val1 : Symbol(TestCase.val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 47))
|
||||
>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 19))
|
||||
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 19))
|
||||
|
||||
readonly val2: ReadonlyArray<T>;
|
||||
>val2 : Symbol(TestCase.val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 3, 38))
|
||||
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 19))
|
||||
}
|
||||
|
||||
interface MultiCaseFixture<T> {
|
||||
>MultiCaseFixture : Symbol(MultiCaseFixture, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 5, 1))
|
||||
>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 27))
|
||||
|
||||
cases: T[];
|
||||
>cases : Symbol(MultiCaseFixture.cases, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 31))
|
||||
>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 27))
|
||||
}
|
||||
|
||||
function subDataFunc(): TestCase<string | number>[] {
|
||||
>subDataFunc : Symbol(subDataFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 9, 1))
|
||||
>TestCase : Symbol(TestCase, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 0, 0))
|
||||
|
||||
return [
|
||||
{ val1: "a", val2: ["a", "b", "c"] },
|
||||
>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 13, 7))
|
||||
>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 13, 18))
|
||||
|
||||
{ val1: 2, val2: [1, 2, 3] },
|
||||
>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 14, 7))
|
||||
>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 14, 16))
|
||||
|
||||
{ val1: ["a", "z"], val2: ["x", "y", "z"] },
|
||||
>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 15, 7))
|
||||
>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 15, 25))
|
||||
|
||||
{ val1: [5, 10], val2: [10, 100, 1000] },
|
||||
>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 16, 7))
|
||||
>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 16, 22))
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
function dataFunc<T>(subFunc: () => T[]): MultiCaseFixture<T> {
|
||||
>dataFunc : Symbol(dataFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 18, 1))
|
||||
>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 18))
|
||||
>subFunc : Symbol(subFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 21))
|
||||
>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 18))
|
||||
>MultiCaseFixture : Symbol(MultiCaseFixture, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 5, 1))
|
||||
>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 18))
|
||||
|
||||
return { cases: subFunc() };
|
||||
>cases : Symbol(cases, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 21, 10))
|
||||
>subFunc : Symbol(subFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 21))
|
||||
}
|
||||
|
||||
function testFunc() {
|
||||
>testFunc : Symbol(testFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 22, 1))
|
||||
|
||||
const fixture = dataFunc<TestCase<string | number>>(subDataFunc);
|
||||
>fixture : Symbol(fixture, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 25, 7))
|
||||
>dataFunc : Symbol(dataFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 18, 1))
|
||||
>TestCase : Symbol(TestCase, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 0, 0))
|
||||
>subDataFunc : Symbol(subDataFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 9, 1))
|
||||
|
||||
fixture.cases.forEach(({ val1, val2 }) => {
|
||||
>fixture.cases.forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
|
||||
>fixture.cases : Symbol(MultiCaseFixture.cases, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 31))
|
||||
>fixture : Symbol(fixture, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 25, 7))
|
||||
>cases : Symbol(MultiCaseFixture.cases, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 31))
|
||||
>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
|
||||
>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 26))
|
||||
>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 32))
|
||||
|
||||
if (Array.isArray(val1)) {
|
||||
>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 26))
|
||||
|
||||
// This should retain val1 as being an array
|
||||
const reversedVal1 = val1.slice().reverse();
|
||||
>reversedVal1 : Symbol(reversedVal1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 29, 15))
|
||||
>val1.slice().reverse : Symbol(Array.reverse, Decl(lib.es5.d.ts, --, --))
|
||||
>val1.slice : Symbol(Array.slice, Decl(lib.es5.d.ts, --, --))
|
||||
>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 26))
|
||||
>slice : Symbol(Array.slice, Decl(lib.es5.d.ts, --, --))
|
||||
>reverse : Symbol(Array.reverse, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
console.log(reversedVal1);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>reversedVal1 : Symbol(reversedVal1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 29, 15))
|
||||
|
||||
} else {
|
||||
console.log(val1);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 26))
|
||||
}
|
||||
console.log(val2);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 32))
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
testFunc();
|
||||
>testFunc : Symbol(testFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 22, 1))
|
||||
|
||||
@ -0,0 +1,147 @@
|
||||
=== tests/cases/compiler/narrowingAssignmentReadonlyRespectsAssertion.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/41984
|
||||
|
||||
interface TestCase<T extends string | number> {
|
||||
readonly val1: T | ReadonlyArray<T>;
|
||||
>val1 : T | readonly T[]
|
||||
|
||||
readonly val2: ReadonlyArray<T>;
|
||||
>val2 : readonly T[]
|
||||
}
|
||||
|
||||
interface MultiCaseFixture<T> {
|
||||
cases: T[];
|
||||
>cases : T[]
|
||||
}
|
||||
|
||||
function subDataFunc(): TestCase<string | number>[] {
|
||||
>subDataFunc : () => TestCase<string | number>[]
|
||||
|
||||
return [
|
||||
>[ { val1: "a", val2: ["a", "b", "c"] }, { val1: 2, val2: [1, 2, 3] }, { val1: ["a", "z"], val2: ["x", "y", "z"] }, { val1: [5, 10], val2: [10, 100, 1000] }, ] : ({ val1: string; val2: string[]; } | { val1: number; val2: number[]; } | { val1: string[]; val2: string[]; } | { val1: number[]; val2: number[]; })[]
|
||||
|
||||
{ val1: "a", val2: ["a", "b", "c"] },
|
||||
>{ val1: "a", val2: ["a", "b", "c"] } : { val1: string; val2: string[]; }
|
||||
>val1 : string
|
||||
>"a" : "a"
|
||||
>val2 : string[]
|
||||
>["a", "b", "c"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>"c" : "c"
|
||||
|
||||
{ val1: 2, val2: [1, 2, 3] },
|
||||
>{ val1: 2, val2: [1, 2, 3] } : { val1: number; val2: number[]; }
|
||||
>val1 : number
|
||||
>2 : 2
|
||||
>val2 : number[]
|
||||
>[1, 2, 3] : number[]
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
{ val1: ["a", "z"], val2: ["x", "y", "z"] },
|
||||
>{ val1: ["a", "z"], val2: ["x", "y", "z"] } : { val1: string[]; val2: string[]; }
|
||||
>val1 : string[]
|
||||
>["a", "z"] : string[]
|
||||
>"a" : "a"
|
||||
>"z" : "z"
|
||||
>val2 : string[]
|
||||
>["x", "y", "z"] : string[]
|
||||
>"x" : "x"
|
||||
>"y" : "y"
|
||||
>"z" : "z"
|
||||
|
||||
{ val1: [5, 10], val2: [10, 100, 1000] },
|
||||
>{ val1: [5, 10], val2: [10, 100, 1000] } : { val1: number[]; val2: number[]; }
|
||||
>val1 : number[]
|
||||
>[5, 10] : number[]
|
||||
>5 : 5
|
||||
>10 : 10
|
||||
>val2 : number[]
|
||||
>[10, 100, 1000] : number[]
|
||||
>10 : 10
|
||||
>100 : 100
|
||||
>1000 : 1000
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
function dataFunc<T>(subFunc: () => T[]): MultiCaseFixture<T> {
|
||||
>dataFunc : <T>(subFunc: () => T[]) => MultiCaseFixture<T>
|
||||
>subFunc : () => T[]
|
||||
|
||||
return { cases: subFunc() };
|
||||
>{ cases: subFunc() } : { cases: T[]; }
|
||||
>cases : T[]
|
||||
>subFunc() : T[]
|
||||
>subFunc : () => T[]
|
||||
}
|
||||
|
||||
function testFunc() {
|
||||
>testFunc : () => void
|
||||
|
||||
const fixture = dataFunc<TestCase<string | number>>(subDataFunc);
|
||||
>fixture : MultiCaseFixture<TestCase<string | number>>
|
||||
>dataFunc<TestCase<string | number>>(subDataFunc) : MultiCaseFixture<TestCase<string | number>>
|
||||
>dataFunc : <T>(subFunc: () => T[]) => MultiCaseFixture<T>
|
||||
>subDataFunc : () => TestCase<string | number>[]
|
||||
|
||||
fixture.cases.forEach(({ val1, val2 }) => {
|
||||
>fixture.cases.forEach(({ val1, val2 }) => { if (Array.isArray(val1)) { // This should retain val1 as being an array const reversedVal1 = val1.slice().reverse(); console.log(reversedVal1); } else { console.log(val1); } console.log(val2); }) : void
|
||||
>fixture.cases.forEach : (callbackfn: (value: TestCase<string | number>, index: number, array: TestCase<string | number>[]) => void, thisArg?: any) => void
|
||||
>fixture.cases : TestCase<string | number>[]
|
||||
>fixture : MultiCaseFixture<TestCase<string | number>>
|
||||
>cases : TestCase<string | number>[]
|
||||
>forEach : (callbackfn: (value: TestCase<string | number>, index: number, array: TestCase<string | number>[]) => void, thisArg?: any) => void
|
||||
>({ val1, val2 }) => { if (Array.isArray(val1)) { // This should retain val1 as being an array const reversedVal1 = val1.slice().reverse(); console.log(reversedVal1); } else { console.log(val1); } console.log(val2); } : ({ val1, val2 }: TestCase<string | number>) => void
|
||||
>val1 : string | number | readonly (string | number)[]
|
||||
>val2 : readonly (string | number)[]
|
||||
|
||||
if (Array.isArray(val1)) {
|
||||
>Array.isArray(val1) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>val1 : string | number | readonly (string | number)[]
|
||||
|
||||
// This should retain val1 as being an array
|
||||
const reversedVal1 = val1.slice().reverse();
|
||||
>reversedVal1 : any[]
|
||||
>val1.slice().reverse() : any[]
|
||||
>val1.slice().reverse : () => any[]
|
||||
>val1.slice() : any[]
|
||||
>val1.slice : (start?: number, end?: number) => any[]
|
||||
>val1 : any[]
|
||||
>slice : (start?: number, end?: number) => any[]
|
||||
>reverse : () => any[]
|
||||
|
||||
console.log(reversedVal1);
|
||||
>console.log(reversedVal1) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>reversedVal1 : any[]
|
||||
|
||||
} else {
|
||||
console.log(val1);
|
||||
>console.log(val1) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>val1 : string | number | readonly (string | number)[]
|
||||
}
|
||||
console.log(val2);
|
||||
>console.log(val2) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>val2 : readonly (string | number)[]
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
testFunc();
|
||||
>testFunc() : void
|
||||
>testFunc : () => void
|
||||
|
||||
@ -176,17 +176,17 @@ function identifyBeast(beast: Beast) {
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
|
||||
if (beast.legs === 4) {
|
||||
>beast.legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(Legged.legs, 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(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(Legged.legs, 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(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(Legged.legs, 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(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 64, 23))
|
||||
>legs : Symbol(legs, Decl(typeGuardIntersectionTypes.ts, 55, 38), Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(Legged.legs, 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 : Beast & Legged
|
||||
>beast : Legged
|
||||
|
||||
if (beast.legs === 4) {
|
||||
>beast.legs === 4 : boolean
|
||||
>beast.legs : number
|
||||
>beast : Beast & Legged & Winged
|
||||
>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 : Beast & Legged & Winged
|
||||
>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 : Beast & Legged & Winged
|
||||
>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 : Beast & Legged
|
||||
>beast : Legged
|
||||
>legs : number
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20): error TS2339: Property 'global' does not exist on type 'never'.
|
||||
The intersection 'I & RegExp' was reduced to 'never' because property 'global' has conflicting types in some constituents.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(36,11): error TS2339: Property 'onChanges' does not exist on type 'C | (Validator & Partial<OnChanges>)'.
|
||||
Property 'onChanges' does not exist on type 'C'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(37,11): error TS2339: Property 'onChanges' does not exist on type 'C | (Validator & Partial<OnChanges>)'.
|
||||
Property 'onChanges' does not exist on type 'C'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (1 errors) ====
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (3 errors) ====
|
||||
interface I { global: string; }
|
||||
var result!: I;
|
||||
var result2!: I;
|
||||
@ -36,8 +40,19 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20)
|
||||
v // Validator & Partial<OnChanges> & C
|
||||
}
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
|
||||
// In 4.1, we introduced a change which _fixed_ a bug with CFA
|
||||
// correctly setting this to be the right object. With 4.2,
|
||||
// we reverted that fix in #42231 which brought behavior back to
|
||||
// before 4.1.
|
||||
if (v.onChanges) {
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'onChanges' does not exist on type 'C | (Validator & Partial<OnChanges>)'.
|
||||
!!! error TS2339: Property 'onChanges' does not exist on type 'C'.
|
||||
v.onChanges({});
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'onChanges' does not exist on type 'C | (Validator & Partial<OnChanges>)'.
|
||||
!!! error TS2339: Property 'onChanges' does not exist on type 'C'.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,11 @@ function foo() {
|
||||
v // Validator & Partial<OnChanges> & C
|
||||
}
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
|
||||
// In 4.1, we introduced a change which _fixed_ a bug with CFA
|
||||
// correctly setting this to be the right object. With 4.2,
|
||||
// we reverted that fix in #42231 which brought behavior back to
|
||||
// before 4.1.
|
||||
if (v.onChanges) {
|
||||
v.onChanges({});
|
||||
}
|
||||
@ -58,6 +63,10 @@ function foo() {
|
||||
v; // Validator & Partial<OnChanges> & C
|
||||
}
|
||||
v; // Validator & Partial<OnChanges> via subtype reduction
|
||||
// In 4.1, we introduced a change which _fixed_ a bug with CFA
|
||||
// correctly setting this to be the right object. With 4.2,
|
||||
// we reverted that fix in #42231 which brought behavior back to
|
||||
// before 4.1.
|
||||
if (v.onChanges) {
|
||||
v.onChanges({});
|
||||
}
|
||||
|
||||
@ -70,15 +70,15 @@ function foo() {
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
>v : Symbol(v, Decl(typeGuardsWithInstanceOf.ts, 25, 7))
|
||||
|
||||
// In 4.1, we introduced a change which _fixed_ a bug with CFA
|
||||
// correctly setting this to be the right object. With 4.2,
|
||||
// we reverted that fix in #42231 which brought behavior back to
|
||||
// before 4.1.
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -65,21 +65,25 @@ function foo() {
|
||||
>C : typeof C
|
||||
|
||||
v // Validator & Partial<OnChanges> & C
|
||||
>v : Validator & Partial<OnChanges> & C
|
||||
>v : C
|
||||
}
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
>v : Validator & Partial<OnChanges>
|
||||
>v : C | (Validator & Partial<OnChanges>)
|
||||
|
||||
// In 4.1, we introduced a change which _fixed_ a bug with CFA
|
||||
// correctly setting this to be the right object. With 4.2,
|
||||
// we reverted that fix in #42231 which brought behavior back to
|
||||
// before 4.1.
|
||||
if (v.onChanges) {
|
||||
>v.onChanges : ((changes: Record<string, unknown>) => void) | undefined
|
||||
>v : Validator & Partial<OnChanges>
|
||||
>onChanges : ((changes: Record<string, unknown>) => void) | undefined
|
||||
>v.onChanges : any
|
||||
>v : C | (Validator & Partial<OnChanges>)
|
||||
>onChanges : any
|
||||
|
||||
v.onChanges({});
|
||||
>v.onChanges({}) : void
|
||||
>v.onChanges : (changes: Record<string, unknown>) => void
|
||||
>v : Validator & Partial<OnChanges>
|
||||
>onChanges : (changes: Record<string, unknown>) => void
|
||||
>v.onChanges({}) : any
|
||||
>v.onChanges : any
|
||||
>v : C | (Validator & Partial<OnChanges>)
|
||||
>onChanges : any
|
||||
>{} : {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
// https://github.com/microsoft/TypeScript/issues/41984
|
||||
|
||||
interface TestCase<T extends string | number> {
|
||||
readonly val1: T | ReadonlyArray<T>;
|
||||
readonly val2: ReadonlyArray<T>;
|
||||
}
|
||||
|
||||
interface MultiCaseFixture<T> {
|
||||
cases: T[];
|
||||
}
|
||||
|
||||
function subDataFunc(): TestCase<string | number>[] {
|
||||
return [
|
||||
{ val1: "a", val2: ["a", "b", "c"] },
|
||||
{ val1: 2, val2: [1, 2, 3] },
|
||||
{ val1: ["a", "z"], val2: ["x", "y", "z"] },
|
||||
{ val1: [5, 10], val2: [10, 100, 1000] },
|
||||
];
|
||||
}
|
||||
|
||||
function dataFunc<T>(subFunc: () => T[]): MultiCaseFixture<T> {
|
||||
return { cases: subFunc() };
|
||||
}
|
||||
|
||||
function testFunc() {
|
||||
const fixture = dataFunc<TestCase<string | number>>(subDataFunc);
|
||||
fixture.cases.forEach(({ val1, val2 }) => {
|
||||
if (Array.isArray(val1)) {
|
||||
// This should retain val1 as being an array
|
||||
const reversedVal1 = val1.slice().reverse();
|
||||
console.log(reversedVal1);
|
||||
} else {
|
||||
console.log(val1);
|
||||
}
|
||||
console.log(val2);
|
||||
});
|
||||
}
|
||||
|
||||
testFunc();
|
||||
@ -30,6 +30,11 @@ function foo() {
|
||||
v // Validator & Partial<OnChanges> & C
|
||||
}
|
||||
v // Validator & Partial<OnChanges> via subtype reduction
|
||||
|
||||
// In 4.1, we introduced a change which _fixed_ a bug with CFA
|
||||
// correctly setting this to be the right object. With 4.2,
|
||||
// we reverted that fix in #42231 which brought behavior back to
|
||||
// before 4.1.
|
||||
if (v.onChanges) {
|
||||
v.onChanges({});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user