diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a6e009c3d72..af8bd6f7c98 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10807,7 +10807,7 @@ namespace ts { } function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean) { - const properties = getPropertiesOfObjectType(target); + const properties = target.flags & TypeFlags.Intersection ? getPropertiesOfUnionOrIntersectionType(target) : getPropertiesOfObjectType(target); for (const targetProp of properties) { if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional)) { const sourceProp = getPropertyOfType(source, targetProp.escapedName); diff --git a/tests/baselines/reference/intersectionTypeInference3.js b/tests/baselines/reference/intersectionTypeInference3.js new file mode 100644 index 00000000000..8a7db286ca2 --- /dev/null +++ b/tests/baselines/reference/intersectionTypeInference3.js @@ -0,0 +1,25 @@ +//// [intersectionTypeInference3.ts] +// Repro from #19682 + +type Nominal = Type & { + [Symbol.species]: Kind; +}; + +type A = Nominal<'A', string>; + +declare const a: Set; +declare const b: Set; + +const c1 = Array.from(a).concat(Array.from(b)); + +// Simpler repro + +declare function from(): T[]; +const c2: ReadonlyArray = from(); + + +//// [intersectionTypeInference3.js] +"use strict"; +// Repro from #19682 +const c1 = Array.from(a).concat(Array.from(b)); +const c2 = from(); diff --git a/tests/baselines/reference/intersectionTypeInference3.symbols b/tests/baselines/reference/intersectionTypeInference3.symbols new file mode 100644 index 00000000000..3945cf64fb6 --- /dev/null +++ b/tests/baselines/reference/intersectionTypeInference3.symbols @@ -0,0 +1,57 @@ +=== tests/cases/conformance/types/intersection/intersectionTypeInference3.ts === +// Repro from #19682 + +type Nominal = Type & { +>Nominal : Symbol(Nominal, Decl(intersectionTypeInference3.ts, 0, 0)) +>Kind : Symbol(Kind, Decl(intersectionTypeInference3.ts, 2, 13)) +>Type : Symbol(Type, Decl(intersectionTypeInference3.ts, 2, 33)) +>Type : Symbol(Type, Decl(intersectionTypeInference3.ts, 2, 33)) + + [Symbol.species]: Kind; +>Symbol.species : Symbol(SymbolConstructor.species, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>species : Symbol(SymbolConstructor.species, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Kind : Symbol(Kind, Decl(intersectionTypeInference3.ts, 2, 13)) + +}; + +type A = Nominal<'A', string>; +>A : Symbol(A, Decl(intersectionTypeInference3.ts, 4, 2)) +>Nominal : Symbol(Nominal, Decl(intersectionTypeInference3.ts, 0, 0)) + +declare const a: Set; +>a : Symbol(a, Decl(intersectionTypeInference3.ts, 8, 13)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) +>A : Symbol(A, Decl(intersectionTypeInference3.ts, 4, 2)) + +declare const b: Set; +>b : Symbol(b, Decl(intersectionTypeInference3.ts, 9, 13)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) +>A : Symbol(A, Decl(intersectionTypeInference3.ts, 4, 2)) + +const c1 = Array.from(a).concat(Array.from(b)); +>c1 : Symbol(c1, Decl(intersectionTypeInference3.ts, 11, 5)) +>Array.from(a).concat : Symbol(Array.concat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>a : Symbol(a, Decl(intersectionTypeInference3.ts, 8, 13)) +>concat : Symbol(Array.concat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>b : Symbol(b, Decl(intersectionTypeInference3.ts, 9, 13)) + +// Simpler repro + +declare function from(): T[]; +>from : Symbol(from, Decl(intersectionTypeInference3.ts, 11, 47)) +>T : Symbol(T, Decl(intersectionTypeInference3.ts, 15, 22)) +>T : Symbol(T, Decl(intersectionTypeInference3.ts, 15, 22)) + +const c2: ReadonlyArray = from(); +>c2 : Symbol(c2, Decl(intersectionTypeInference3.ts, 16, 5)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>A : Symbol(A, Decl(intersectionTypeInference3.ts, 4, 2)) +>from : Symbol(from, Decl(intersectionTypeInference3.ts, 11, 47)) + diff --git a/tests/baselines/reference/intersectionTypeInference3.types b/tests/baselines/reference/intersectionTypeInference3.types new file mode 100644 index 00000000000..9fca37af8c1 --- /dev/null +++ b/tests/baselines/reference/intersectionTypeInference3.types @@ -0,0 +1,61 @@ +=== tests/cases/conformance/types/intersection/intersectionTypeInference3.ts === +// Repro from #19682 + +type Nominal = Type & { +>Nominal : Nominal +>Kind : Kind +>Type : Type +>Type : Type + + [Symbol.species]: Kind; +>Symbol.species : symbol +>Symbol : SymbolConstructor +>species : symbol +>Kind : Kind + +}; + +type A = Nominal<'A', string>; +>A : Nominal<"A", string> +>Nominal : Nominal + +declare const a: Set; +>a : Set> +>Set : Set +>A : Nominal<"A", string> + +declare const b: Set; +>b : Set> +>Set : Set +>A : Nominal<"A", string> + +const c1 = Array.from(a).concat(Array.from(b)); +>c1 : Nominal<"A", string>[] +>Array.from(a).concat(Array.from(b)) : Nominal<"A", string>[] +>Array.from(a).concat : { (...items: ReadonlyArray>[]): Nominal<"A", string>[]; (...items: (Nominal<"A", string> | ReadonlyArray>)[]): Nominal<"A", string>[]; } +>Array.from(a) : Nominal<"A", string>[] +>Array.from : { (iterable: Iterable): T[]; (iterable: Iterable, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; (arrayLike: ArrayLike): T[]; (arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; } +>Array : ArrayConstructor +>from : { (iterable: Iterable): T[]; (iterable: Iterable, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; (arrayLike: ArrayLike): T[]; (arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; } +>a : Set> +>concat : { (...items: ReadonlyArray>[]): Nominal<"A", string>[]; (...items: (Nominal<"A", string> | ReadonlyArray>)[]): Nominal<"A", string>[]; } +>Array.from(b) : Nominal<"A", string>[] +>Array.from : { (iterable: Iterable): T[]; (iterable: Iterable, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; (arrayLike: ArrayLike): T[]; (arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; } +>Array : ArrayConstructor +>from : { (iterable: Iterable): T[]; (iterable: Iterable, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; (arrayLike: ArrayLike): T[]; (arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; } +>b : Set> + +// Simpler repro + +declare function from(): T[]; +>from : () => T[] +>T : T +>T : T + +const c2: ReadonlyArray = from(); +>c2 : ReadonlyArray> +>ReadonlyArray : ReadonlyArray +>A : Nominal<"A", string> +>from() : Nominal<"A", string>[] +>from : () => T[] + diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt index 2feed16ac0a..d692364d264 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt +++ b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt @@ -1,9 +1,9 @@ tests/cases/conformance/jsx/file.tsx(9,33): error TS2322: Type '{ a: number; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: number; }'. Type '{ a: number; }' is not assignable to type '{ b: {}; a: number; }'. Property 'b' is missing in type '{ a: number; }'. -tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. - Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. - Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. +tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'. + Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'. + Type '{ b: number; }' is not assignable to type '{ b: {}; a: {}; }'. Property 'a' is missing in type '{ b: number; }'. Type 'T' is not assignable to type 'IntrinsicAttributes'. Type '{ b: number; }' has no properties in common with type 'IntrinsicAttributes'. @@ -25,9 +25,9 @@ tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T' is not assig !!! error TS2322: Property 'b' is missing in type '{ a: number; }'. let a2 = // missing a ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. -!!! error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. -!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. +!!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'. +!!! error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'. +!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: {}; a: {}; }'. !!! error TS2322: Property 'a' is missing in type '{ b: number; }'. !!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes'. !!! error TS2322: Type '{ b: number; }' has no properties in common with type 'IntrinsicAttributes'. diff --git a/tests/cases/conformance/types/intersection/intersectionTypeInference3.ts b/tests/cases/conformance/types/intersection/intersectionTypeInference3.ts new file mode 100644 index 00000000000..ceaff10f7f1 --- /dev/null +++ b/tests/cases/conformance/types/intersection/intersectionTypeInference3.ts @@ -0,0 +1,20 @@ +// @strict: true +// @target: es2015 + +// Repro from #19682 + +type Nominal = Type & { + [Symbol.species]: Kind; +}; + +type A = Nominal<'A', string>; + +declare const a: Set; +declare const b: Set; + +const c1 = Array.from(a).concat(Array.from(b)); + +// Simpler repro + +declare function from(): T[]; +const c2: ReadonlyArray = from();