Merge pull request #38669 from typescript-bot/pick/38565/release-3.9
🤖 Pick PR #38565 (Perform intersection reduction befo...) into release-3.9
This commit is contained in:
commit
59d7d00005
|
@ -10144,7 +10144,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function getPropertiesOfType(type: Type): Symbol[] {
|
||||
type = getApparentType(getReducedType(type));
|
||||
type = getReducedApparentType(type);
|
||||
return type.flags & TypeFlags.UnionOrIntersection ?
|
||||
getPropertiesOfUnionOrIntersectionType(<UnionType>type) :
|
||||
getPropertiesOfObjectType(type);
|
||||
|
@ -10500,6 +10500,14 @@ namespace ts {
|
|||
t;
|
||||
}
|
||||
|
||||
function getReducedApparentType(type: Type): Type {
|
||||
// Since getApparentType may return a non-reduced union or intersection type, we need to perform
|
||||
// type reduction both before and after obtaining the apparent type. For example, given a type parameter
|
||||
// 'T extends A | B', the type 'T & X' becomes 'A & X | B & X' after obtaining the apparent type, and
|
||||
// that type may need futher reduction to remove empty intersections.
|
||||
return getReducedType(getApparentType(getReducedType(type)));
|
||||
}
|
||||
|
||||
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String): Symbol | undefined {
|
||||
let singleProp: Symbol | undefined;
|
||||
let propSet: Map<Symbol> | undefined;
|
||||
|
@ -10721,7 +10729,7 @@ namespace ts {
|
|||
* @param name a name of property to look up in a given type
|
||||
*/
|
||||
function getPropertyOfType(type: Type, name: __String): Symbol | undefined {
|
||||
type = getApparentType(getReducedType(type));
|
||||
type = getReducedApparentType(type);
|
||||
if (type.flags & TypeFlags.Object) {
|
||||
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
const symbol = resolved.members.get(name);
|
||||
|
@ -10759,7 +10767,7 @@ namespace ts {
|
|||
* maps primitive types and type parameters are to their apparent types.
|
||||
*/
|
||||
function getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[] {
|
||||
return getSignaturesOfStructuredType(getApparentType(getReducedType(type)), kind);
|
||||
return getSignaturesOfStructuredType(getReducedApparentType(type), kind);
|
||||
}
|
||||
|
||||
function getIndexInfoOfStructuredType(type: Type, kind: IndexKind): IndexInfo | undefined {
|
||||
|
@ -10777,13 +10785,13 @@ namespace ts {
|
|||
// Return the indexing info of the given kind in the given type. Creates synthetic union index types when necessary and
|
||||
// maps primitive types and type parameters are to their apparent types.
|
||||
function getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined {
|
||||
return getIndexInfoOfStructuredType(getApparentType(getReducedType(type)), kind);
|
||||
return getIndexInfoOfStructuredType(getReducedApparentType(type), kind);
|
||||
}
|
||||
|
||||
// Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and
|
||||
// maps primitive types and type parameters are to their apparent types.
|
||||
function getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined {
|
||||
return getIndexTypeOfStructuredType(getApparentType(getReducedType(type)), kind);
|
||||
return getIndexTypeOfStructuredType(getReducedApparentType(type), kind);
|
||||
}
|
||||
|
||||
function getImplicitIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined {
|
||||
|
@ -13154,7 +13162,7 @@ namespace ts {
|
|||
// In the following we resolve T[K] to the type of the property in T selected by K.
|
||||
// We treat boolean as different from other unions to improve errors;
|
||||
// skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'.
|
||||
const apparentObjectType = getApparentType(getReducedType(objectType));
|
||||
const apparentObjectType = getReducedApparentType(objectType);
|
||||
if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Boolean)) {
|
||||
const propTypes: Type[] = [];
|
||||
let wasMissingProp = false;
|
||||
|
|
|
@ -121,3 +121,35 @@ tests/cases/conformance/types/intersection/intersectionReduction.ts(81,1): error
|
|||
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
|
||||
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
|
||||
|
||||
// Repro from #38549
|
||||
|
||||
interface A2 {
|
||||
kind: "A";
|
||||
a: number;
|
||||
}
|
||||
|
||||
interface B2 {
|
||||
kind: "B";
|
||||
b: number;
|
||||
}
|
||||
|
||||
declare const shouldBeB: (A2 | B2) & B2;
|
||||
const b: B2 = shouldBeB; // works
|
||||
|
||||
function inGeneric<T extends A2 | B2>(alsoShouldBeB: T & B2) {
|
||||
const b: B2 = alsoShouldBeB;
|
||||
}
|
||||
|
||||
// Repro from #38542
|
||||
|
||||
interface ABI {
|
||||
kind: 'a' | 'b';
|
||||
}
|
||||
|
||||
declare class CA { kind: 'a'; a: string; x: number };
|
||||
declare class CB { kind: 'b'; b: string; y: number };
|
||||
|
||||
function bar<T extends CA | CB>(x: T & CA) {
|
||||
let ab: ABI = x;
|
||||
}
|
||||
|
|
@ -108,6 +108,38 @@ const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a
|
|||
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
|
||||
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
|
||||
|
||||
// Repro from #38549
|
||||
|
||||
interface A2 {
|
||||
kind: "A";
|
||||
a: number;
|
||||
}
|
||||
|
||||
interface B2 {
|
||||
kind: "B";
|
||||
b: number;
|
||||
}
|
||||
|
||||
declare const shouldBeB: (A2 | B2) & B2;
|
||||
const b: B2 = shouldBeB; // works
|
||||
|
||||
function inGeneric<T extends A2 | B2>(alsoShouldBeB: T & B2) {
|
||||
const b: B2 = alsoShouldBeB;
|
||||
}
|
||||
|
||||
// Repro from #38542
|
||||
|
||||
interface ABI {
|
||||
kind: 'a' | 'b';
|
||||
}
|
||||
|
||||
declare class CA { kind: 'a'; a: string; x: number };
|
||||
declare class CB { kind: 'b'; b: string; y: number };
|
||||
|
||||
function bar<T extends CA | CB>(x: T & CA) {
|
||||
let ab: ABI = x;
|
||||
}
|
||||
|
||||
|
||||
//// [intersectionReduction.js]
|
||||
ab.kind; // Error
|
||||
|
@ -128,3 +160,12 @@ var f1 = function (t) { return t; };
|
|||
var f2 = function (t) { return t; };
|
||||
var f3 = function (t) { return t; };
|
||||
var f4 = function (t) { return t; };
|
||||
var b = shouldBeB; // works
|
||||
function inGeneric(alsoShouldBeB) {
|
||||
var b = alsoShouldBeB;
|
||||
}
|
||||
;
|
||||
;
|
||||
function bar(x) {
|
||||
var ab = x;
|
||||
}
|
||||
|
|
|
@ -373,3 +373,87 @@ const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)):
|
|||
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
|
||||
>t : Symbol(t, Decl(intersectionReduction.ts, 107, 12))
|
||||
|
||||
// Repro from #38549
|
||||
|
||||
interface A2 {
|
||||
>A2 : Symbol(A2, Decl(intersectionReduction.ts, 107, 93))
|
||||
|
||||
kind: "A";
|
||||
>kind : Symbol(A2.kind, Decl(intersectionReduction.ts, 111, 14))
|
||||
|
||||
a: number;
|
||||
>a : Symbol(A2.a, Decl(intersectionReduction.ts, 112, 14))
|
||||
}
|
||||
|
||||
interface B2 {
|
||||
>B2 : Symbol(B2, Decl(intersectionReduction.ts, 114, 1))
|
||||
|
||||
kind: "B";
|
||||
>kind : Symbol(B2.kind, Decl(intersectionReduction.ts, 116, 14))
|
||||
|
||||
b: number;
|
||||
>b : Symbol(B2.b, Decl(intersectionReduction.ts, 117, 14))
|
||||
}
|
||||
|
||||
declare const shouldBeB: (A2 | B2) & B2;
|
||||
>shouldBeB : Symbol(shouldBeB, Decl(intersectionReduction.ts, 121, 13))
|
||||
>A2 : Symbol(A2, Decl(intersectionReduction.ts, 107, 93))
|
||||
>B2 : Symbol(B2, Decl(intersectionReduction.ts, 114, 1))
|
||||
>B2 : Symbol(B2, Decl(intersectionReduction.ts, 114, 1))
|
||||
|
||||
const b: B2 = shouldBeB; // works
|
||||
>b : Symbol(b, Decl(intersectionReduction.ts, 122, 5))
|
||||
>B2 : Symbol(B2, Decl(intersectionReduction.ts, 114, 1))
|
||||
>shouldBeB : Symbol(shouldBeB, Decl(intersectionReduction.ts, 121, 13))
|
||||
|
||||
function inGeneric<T extends A2 | B2>(alsoShouldBeB: T & B2) {
|
||||
>inGeneric : Symbol(inGeneric, Decl(intersectionReduction.ts, 122, 24))
|
||||
>T : Symbol(T, Decl(intersectionReduction.ts, 124, 19))
|
||||
>A2 : Symbol(A2, Decl(intersectionReduction.ts, 107, 93))
|
||||
>B2 : Symbol(B2, Decl(intersectionReduction.ts, 114, 1))
|
||||
>alsoShouldBeB : Symbol(alsoShouldBeB, Decl(intersectionReduction.ts, 124, 38))
|
||||
>T : Symbol(T, Decl(intersectionReduction.ts, 124, 19))
|
||||
>B2 : Symbol(B2, Decl(intersectionReduction.ts, 114, 1))
|
||||
|
||||
const b: B2 = alsoShouldBeB;
|
||||
>b : Symbol(b, Decl(intersectionReduction.ts, 125, 9))
|
||||
>B2 : Symbol(B2, Decl(intersectionReduction.ts, 114, 1))
|
||||
>alsoShouldBeB : Symbol(alsoShouldBeB, Decl(intersectionReduction.ts, 124, 38))
|
||||
}
|
||||
|
||||
// Repro from #38542
|
||||
|
||||
interface ABI {
|
||||
>ABI : Symbol(ABI, Decl(intersectionReduction.ts, 126, 1))
|
||||
|
||||
kind: 'a' | 'b';
|
||||
>kind : Symbol(ABI.kind, Decl(intersectionReduction.ts, 130, 15))
|
||||
}
|
||||
|
||||
declare class CA { kind: 'a'; a: string; x: number };
|
||||
>CA : Symbol(CA, Decl(intersectionReduction.ts, 132, 1))
|
||||
>kind : Symbol(CA.kind, Decl(intersectionReduction.ts, 134, 18))
|
||||
>a : Symbol(CA.a, Decl(intersectionReduction.ts, 134, 29))
|
||||
>x : Symbol(CA.x, Decl(intersectionReduction.ts, 134, 40))
|
||||
|
||||
declare class CB { kind: 'b'; b: string; y: number };
|
||||
>CB : Symbol(CB, Decl(intersectionReduction.ts, 134, 53))
|
||||
>kind : Symbol(CB.kind, Decl(intersectionReduction.ts, 135, 18))
|
||||
>b : Symbol(CB.b, Decl(intersectionReduction.ts, 135, 29))
|
||||
>y : Symbol(CB.y, Decl(intersectionReduction.ts, 135, 40))
|
||||
|
||||
function bar<T extends CA | CB>(x: T & CA) {
|
||||
>bar : Symbol(bar, Decl(intersectionReduction.ts, 135, 53))
|
||||
>T : Symbol(T, Decl(intersectionReduction.ts, 137, 13))
|
||||
>CA : Symbol(CA, Decl(intersectionReduction.ts, 132, 1))
|
||||
>CB : Symbol(CB, Decl(intersectionReduction.ts, 134, 53))
|
||||
>x : Symbol(x, Decl(intersectionReduction.ts, 137, 32))
|
||||
>T : Symbol(T, Decl(intersectionReduction.ts, 137, 13))
|
||||
>CA : Symbol(CA, Decl(intersectionReduction.ts, 132, 1))
|
||||
|
||||
let ab: ABI = x;
|
||||
>ab : Symbol(ab, Decl(intersectionReduction.ts, 138, 7))
|
||||
>ABI : Symbol(ABI, Decl(intersectionReduction.ts, 126, 1))
|
||||
>x : Symbol(x, Decl(intersectionReduction.ts, 137, 32))
|
||||
}
|
||||
|
||||
|
|
|
@ -315,3 +315,65 @@ const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)):
|
|||
>dataB : boolean
|
||||
>t : number
|
||||
|
||||
// Repro from #38549
|
||||
|
||||
interface A2 {
|
||||
kind: "A";
|
||||
>kind : "A"
|
||||
|
||||
a: number;
|
||||
>a : number
|
||||
}
|
||||
|
||||
interface B2 {
|
||||
kind: "B";
|
||||
>kind : "B"
|
||||
|
||||
b: number;
|
||||
>b : number
|
||||
}
|
||||
|
||||
declare const shouldBeB: (A2 | B2) & B2;
|
||||
>shouldBeB : B2
|
||||
|
||||
const b: B2 = shouldBeB; // works
|
||||
>b : B2
|
||||
>shouldBeB : B2
|
||||
|
||||
function inGeneric<T extends A2 | B2>(alsoShouldBeB: T & B2) {
|
||||
>inGeneric : <T extends A2 | B2>(alsoShouldBeB: T & B2) => void
|
||||
>alsoShouldBeB : T & B2
|
||||
|
||||
const b: B2 = alsoShouldBeB;
|
||||
>b : B2
|
||||
>alsoShouldBeB : T & B2
|
||||
}
|
||||
|
||||
// Repro from #38542
|
||||
|
||||
interface ABI {
|
||||
kind: 'a' | 'b';
|
||||
>kind : "a" | "b"
|
||||
}
|
||||
|
||||
declare class CA { kind: 'a'; a: string; x: number };
|
||||
>CA : CA
|
||||
>kind : "a"
|
||||
>a : string
|
||||
>x : number
|
||||
|
||||
declare class CB { kind: 'b'; b: string; y: number };
|
||||
>CB : CB
|
||||
>kind : "b"
|
||||
>b : string
|
||||
>y : number
|
||||
|
||||
function bar<T extends CA | CB>(x: T & CA) {
|
||||
>bar : <T extends CA | CB>(x: T & CA) => void
|
||||
>x : T & CA
|
||||
|
||||
let ab: ABI = x;
|
||||
>ab : ABI
|
||||
>x : T & CA
|
||||
}
|
||||
|
||||
|
|
|
@ -108,3 +108,35 @@ type Container<Type extends string> = {
|
|||
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
|
||||
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
|
||||
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
|
||||
|
||||
// Repro from #38549
|
||||
|
||||
interface A2 {
|
||||
kind: "A";
|
||||
a: number;
|
||||
}
|
||||
|
||||
interface B2 {
|
||||
kind: "B";
|
||||
b: number;
|
||||
}
|
||||
|
||||
declare const shouldBeB: (A2 | B2) & B2;
|
||||
const b: B2 = shouldBeB; // works
|
||||
|
||||
function inGeneric<T extends A2 | B2>(alsoShouldBeB: T & B2) {
|
||||
const b: B2 = alsoShouldBeB;
|
||||
}
|
||||
|
||||
// Repro from #38542
|
||||
|
||||
interface ABI {
|
||||
kind: 'a' | 'b';
|
||||
}
|
||||
|
||||
declare class CA { kind: 'a'; a: string; x: number };
|
||||
declare class CB { kind: 'b'; b: string; y: number };
|
||||
|
||||
function bar<T extends CA | CB>(x: T & CA) {
|
||||
let ab: ABI = x;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue