diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7df196699f8..14945a1796e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13791,6 +13791,19 @@ namespace ts { return false; } + function getBestMatchIndexedAccessTypeOrUndefined(source: Type, target: Type, nameType: Type) { + const idx = getIndexedAccessTypeOrUndefined(target, nameType); + if (idx) { + return idx; + } + if (target.flags & TypeFlags.Union) { + const best = getBestMatchingType(source, target as UnionType); + if (best) { + return getIndexedAccessTypeOrUndefined(best, nameType); + } + } + } + type ElaborationIterator = IterableIterator<{ errorNode: Node, innerExpression: Expression | undefined, nameType: Type, errorMessage?: DiagnosticMessage | undefined }>; /** * For every element returned from the iterator, checks that element to issue an error on a property of that element's type @@ -13809,7 +13822,7 @@ namespace ts { let reportedError = false; for (let status = iterator.next(); !status.done; status = iterator.next()) { const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value; - const targetPropType = getIndexedAccessTypeOrUndefined(target, nameType); + const targetPropType = getBestMatchIndexedAccessTypeOrUndefined(source, target, nameType); if (!targetPropType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables const sourcePropType = getIndexedAccessTypeOrUndefined(source, nameType); if (sourcePropType && !checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) { @@ -14942,7 +14955,7 @@ namespace ts { let reducedTarget = target; let checkTypes: Type[] | undefined; if (target.flags & TypeFlags.Union) { - reducedTarget = findMatchingDiscriminantType(source, target) || filterPrimitivesIfContainsNonPrimitive(target); + reducedTarget = findMatchingDiscriminantType(source, target, isRelatedTo) || filterPrimitivesIfContainsNonPrimitive(target); checkTypes = reducedTarget.flags & TypeFlags.Union ? (reducedTarget).types : [reducedTarget]; } for (const prop of getPropertiesOfType(source)) { @@ -15034,103 +15047,12 @@ namespace ts { } } if (reportErrors) { - const bestMatchingType = - findMatchingDiscriminantType(source, target) || - findMatchingTypeReferenceOrTypeAliasReference(source, target) || - findBestTypeForObjectLiteral(source, target) || - findBestTypeForInvokable(source, target) || - findMostOverlappyType(source, target); - + const bestMatchingType = getBestMatchingType(source, target, isRelatedTo); isRelatedTo(source, bestMatchingType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true); } return Ternary.False; } - function findMatchingTypeReferenceOrTypeAliasReference(source: Type, unionTarget: UnionOrIntersectionType) { - const sourceObjectFlags = getObjectFlags(source); - if (sourceObjectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous) && unionTarget.flags & TypeFlags.Union) { - return find(unionTarget.types, target => { - if (target.flags & TypeFlags.Object) { - const overlapObjFlags = sourceObjectFlags & getObjectFlags(target); - if (overlapObjFlags & ObjectFlags.Reference) { - return (source as TypeReference).target === (target as TypeReference).target; - } - if (overlapObjFlags & ObjectFlags.Anonymous) { - return !!(source as AnonymousType).aliasSymbol && (source as AnonymousType).aliasSymbol === (target as AnonymousType).aliasSymbol; - } - } - return false; - }); - } - } - - function findBestTypeForObjectLiteral(source: Type, unionTarget: UnionOrIntersectionType) { - if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && forEachType(unionTarget, isArrayLikeType)) { - return find(unionTarget.types, t => !isArrayLikeType(t)); - } - } - - function findBestTypeForInvokable(source: Type, unionTarget: UnionOrIntersectionType) { - let signatureKind = SignatureKind.Call; - const hasSignatures = getSignaturesOfType(source, signatureKind).length > 0 || - (signatureKind = SignatureKind.Construct, getSignaturesOfType(source, signatureKind).length > 0); - if (hasSignatures) { - return find(unionTarget.types, t => getSignaturesOfType(t, signatureKind).length > 0); - } - } - - function findMostOverlappyType(source: Type, unionTarget: UnionOrIntersectionType) { - let bestMatch: Type | undefined; - let matchingCount = 0; - for (const target of unionTarget.types) { - const overlap = getIntersectionType([getIndexType(source), getIndexType(target)]); - if (overlap.flags & TypeFlags.Index) { - // perfect overlap of keys - bestMatch = target; - matchingCount = Infinity; - } - else if (overlap.flags & TypeFlags.Union) { - // We only want to account for literal types otherwise. - // If we have a union of index types, it seems likely that we - // needed to elaborate between two generic mapped types anyway. - const len = length(filter((overlap as UnionType).types, isUnitType)); - if (len >= matchingCount) { - bestMatch = target; - matchingCount = len; - } - } - else if (isUnitType(overlap) && 1 >= matchingCount) { - bestMatch = target; - matchingCount = 1; - } - } - return bestMatch; - } - - function filterPrimitivesIfContainsNonPrimitive(type: UnionType) { - if (maybeTypeOfKind(type, TypeFlags.NonPrimitive)) { - const result = filterType(type, t => !(t.flags & TypeFlags.Primitive)); - if (!(result.flags & TypeFlags.Never)) { - return result; - } - } - return type; - } - - // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly - function findMatchingDiscriminantType(source: Type, target: Type) { - if (target.flags & TypeFlags.Union && source.flags & (TypeFlags.Intersection | TypeFlags.Object)) { - const sourceProperties = getPropertiesOfType(source); - if (sourceProperties) { - const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); - if (sourcePropertiesFiltered) { - return discriminateTypeByDiscriminableItems(target, map(sourcePropertiesFiltered, p => ([() => getTypeOfSymbol(p), p.escapedName] as [() => Type, __String])), isRelatedTo); - } - } - } - return undefined; - } - function typeRelatedToEachType(source: Type, target: IntersectionType, reportErrors: boolean): Ternary { let result = Ternary.True; const targetTypes = target.types; @@ -16303,6 +16225,14 @@ namespace ts { } } + function getBestMatchingType(source: Type, target: UnionOrIntersectionType, isRelatedTo = compareTypesAssignable) { + return findMatchingDiscriminantType(source, target, isRelatedTo) || + findMatchingTypeReferenceOrTypeAliasReference(source, target) || + findBestTypeForObjectLiteral(source, target) || + findBestTypeForInvokable(source, target) || + findMostOverlappyType(source, target); + } + function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary): Type | undefined; function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue: Type): Type; function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue?: Type) { @@ -36663,6 +36593,91 @@ namespace ts { } return false; } + + function findMatchingTypeReferenceOrTypeAliasReference(source: Type, unionTarget: UnionOrIntersectionType) { + const sourceObjectFlags = getObjectFlags(source); + if (sourceObjectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous) && unionTarget.flags & TypeFlags.Union) { + return find(unionTarget.types, target => { + if (target.flags & TypeFlags.Object) { + const overlapObjFlags = sourceObjectFlags & getObjectFlags(target); + if (overlapObjFlags & ObjectFlags.Reference) { + return (source as TypeReference).target === (target as TypeReference).target; + } + if (overlapObjFlags & ObjectFlags.Anonymous) { + return !!(source as AnonymousType).aliasSymbol && (source as AnonymousType).aliasSymbol === (target as AnonymousType).aliasSymbol; + } + } + return false; + }); + } + } + + function findBestTypeForObjectLiteral(source: Type, unionTarget: UnionOrIntersectionType) { + if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && forEachType(unionTarget, isArrayLikeType)) { + return find(unionTarget.types, t => !isArrayLikeType(t)); + } + } + + function findBestTypeForInvokable(source: Type, unionTarget: UnionOrIntersectionType) { + let signatureKind = SignatureKind.Call; + const hasSignatures = getSignaturesOfType(source, signatureKind).length > 0 || + (signatureKind = SignatureKind.Construct, getSignaturesOfType(source, signatureKind).length > 0); + if (hasSignatures) { + return find(unionTarget.types, t => getSignaturesOfType(t, signatureKind).length > 0); + } + } + + function findMostOverlappyType(source: Type, unionTarget: UnionOrIntersectionType) { + let bestMatch: Type | undefined; + let matchingCount = 0; + for (const target of unionTarget.types) { + const overlap = getIntersectionType([getIndexType(source), getIndexType(target)]); + if (overlap.flags & TypeFlags.Index) { + // perfect overlap of keys + bestMatch = target; + matchingCount = Infinity; + } + else if (overlap.flags & TypeFlags.Union) { + // We only want to account for literal types otherwise. + // If we have a union of index types, it seems likely that we + // needed to elaborate between two generic mapped types anyway. + const len = length(filter((overlap as UnionType).types, isUnitType)); + if (len >= matchingCount) { + bestMatch = target; + matchingCount = len; + } + } + else if (isUnitType(overlap) && 1 >= matchingCount) { + bestMatch = target; + matchingCount = 1; + } + } + return bestMatch; + } + + function filterPrimitivesIfContainsNonPrimitive(type: UnionType) { + if (maybeTypeOfKind(type, TypeFlags.NonPrimitive)) { + const result = filterType(type, t => !(t.flags & TypeFlags.Primitive)); + if (!(result.flags & TypeFlags.Never)) { + return result; + } + } + return type; + } + + // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly + function findMatchingDiscriminantType(source: Type, target: Type, isRelatedTo: (source: Type, target: Type) => Ternary) { + if (target.flags & TypeFlags.Union && source.flags & (TypeFlags.Intersection | TypeFlags.Object)) { + const sourceProperties = getPropertiesOfType(source); + if (sourceProperties) { + const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); + if (sourcePropertiesFiltered) { + return discriminateTypeByDiscriminableItems(target, map(sourcePropertiesFiltered, p => ([() => getTypeOfSymbol(p), p.escapedName] as [() => Type, __String])), isRelatedTo); + } + } + } + return undefined; + } } function isNotAccessor(declaration: Declaration): boolean { diff --git a/tests/baselines/reference/deepExcessPropertyCheckingWhenTargetIsIntersection.errors.txt b/tests/baselines/reference/deepExcessPropertyCheckingWhenTargetIsIntersection.errors.txt index 975f2a37d38..f4b271006f4 100644 --- a/tests/baselines/reference/deepExcessPropertyCheckingWhenTargetIsIntersection.errors.txt +++ b/tests/baselines/reference/deepExcessPropertyCheckingWhenTargetIsIntersection.errors.txt @@ -1,9 +1,7 @@ tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts(21,33): error TS2322: Type '{ INVALID_PROP_NAME: string; ariaLabel: string; }' is not assignable to type 'ITestProps'. Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'ITestProps'. -tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts(27,34): error TS2345: Argument of type '{ icon: { props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }; }' is not assignable to parameter of type '(TestProps & { children?: number; }) | ({ props2: { x: number; }; } & { children?: number; })'. - The types of 'icon.props' are incompatible between these types. - Type '{ INVALID_PROP_NAME: string; ariaLabel: string; }' is not assignable to type 'ITestProps'. - Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'ITestProps'. +tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts(27,34): error TS2322: Type '{ INVALID_PROP_NAME: string; ariaLabel: string; }' is not assignable to type 'ITestProps'. + Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'ITestProps'. ==== tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts (2 errors) ==== @@ -39,8 +37,7 @@ tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts(27,34 TestComponent2({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }}); ~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '{ icon: { props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }; }' is not assignable to parameter of type '(TestProps & { children?: number; }) | ({ props2: { x: number; }; } & { children?: number; })'. -!!! error TS2345: The types of 'icon.props' are incompatible between these types. -!!! error TS2345: Type '{ INVALID_PROP_NAME: string; ariaLabel: string; }' is not assignable to type 'ITestProps'. -!!! error TS2345: Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'ITestProps'. +!!! error TS2322: Type '{ INVALID_PROP_NAME: string; ariaLabel: string; }' is not assignable to type 'ITestProps'. +!!! error TS2322: Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'ITestProps'. +!!! related TS6500 tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts:14:3: The expected type comes from property 'props' which is declared here on type 'NestedProp' \ No newline at end of file diff --git a/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.errors.txt b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.errors.txt new file mode 100644 index 00000000000..62c559e417b --- /dev/null +++ b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.errors.txt @@ -0,0 +1,77 @@ +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(17,7): error TS2322: Type '() => number[]' is not assignable to type '() => Promise'. + Type 'number[]' is missing the following properties from type 'Promise': then, catch +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(18,16): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(19,16): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(20,16): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(21,16): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(22,16): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(23,16): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(24,16): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(25,16): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(26,16): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts(27,16): error TS2322: Type 'number' is not assignable to type 'Promise'. + + +==== tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts (11 errors) ==== + interface Stuff { + a?: () => Promise; + b: () => Promise; + c: () => Promise; + d: () => Promise; + e: () => Promise; + f: () => Promise; + g: () => Promise; + h: () => Promise; + i: () => Promise; + j: () => Promise; + k: () => Promise; + } + + function foo(): Stuff | string { + return { + a() { return [123] }, + ~ +!!! error TS2322: Type '() => number[]' is not assignable to type '() => Promise'. +!!! error TS2322: Type 'number[]' is missing the following properties from type 'Promise': then, catch + b: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:3:8: The expected type comes from the return type of this signature. + c: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:4:8: The expected type comes from the return type of this signature. + d: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:5:8: The expected type comes from the return type of this signature. + e: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:6:8: The expected type comes from the return type of this signature. + f: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:7:8: The expected type comes from the return type of this signature. + g: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:8:8: The expected type comes from the return type of this signature. + h: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:9:8: The expected type comes from the return type of this signature. + i: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:10:8: The expected type comes from the return type of this signature. + j: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:11:8: The expected type comes from the return type of this signature. + k: () => 123 + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts:12:8: The expected type comes from the return type of this signature. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.js b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.js new file mode 100644 index 00000000000..c90a2513e25 --- /dev/null +++ b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.js @@ -0,0 +1,47 @@ +//// [errorOnUnionVsObjectShouldDeeplyDisambiguate.ts] +interface Stuff { + a?: () => Promise; + b: () => Promise; + c: () => Promise; + d: () => Promise; + e: () => Promise; + f: () => Promise; + g: () => Promise; + h: () => Promise; + i: () => Promise; + j: () => Promise; + k: () => Promise; + } + + function foo(): Stuff | string { + return { + a() { return [123] }, + b: () => "hello", + c: () => "hello", + d: () => "hello", + e: () => "hello", + f: () => "hello", + g: () => "hello", + h: () => "hello", + i: () => "hello", + j: () => "hello", + k: () => 123 + } + } + +//// [errorOnUnionVsObjectShouldDeeplyDisambiguate.js] +function foo() { + return { + a: function () { return [123]; }, + b: function () { return "hello"; }, + c: function () { return "hello"; }, + d: function () { return "hello"; }, + e: function () { return "hello"; }, + f: function () { return "hello"; }, + g: function () { return "hello"; }, + h: function () { return "hello"; }, + i: function () { return "hello"; }, + j: function () { return "hello"; }, + k: function () { return 123; } + }; +} diff --git a/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.symbols b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.symbols new file mode 100644 index 00000000000..4f58eeca75a --- /dev/null +++ b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.symbols @@ -0,0 +1,88 @@ +=== tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts === +interface Stuff { +>Stuff : Symbol(Stuff, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 0, 0)) + + a?: () => Promise; +>a : Symbol(Stuff.a, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 0, 17)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + b: () => Promise; +>b : Symbol(Stuff.b, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 1, 32)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + c: () => Promise; +>c : Symbol(Stuff.c, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 2, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + d: () => Promise; +>d : Symbol(Stuff.d, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 3, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + e: () => Promise; +>e : Symbol(Stuff.e, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 4, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + f: () => Promise; +>f : Symbol(Stuff.f, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 5, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + g: () => Promise; +>g : Symbol(Stuff.g, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 6, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + h: () => Promise; +>h : Symbol(Stuff.h, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 7, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + i: () => Promise; +>i : Symbol(Stuff.i, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 8, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + j: () => Promise; +>j : Symbol(Stuff.j, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 9, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + k: () => Promise; +>k : Symbol(Stuff.k, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 10, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + } + + function foo(): Stuff | string { +>foo : Symbol(foo, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 12, 3)) +>Stuff : Symbol(Stuff, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 0, 0)) + + return { + a() { return [123] }, +>a : Symbol(a, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 15, 12)) + + b: () => "hello", +>b : Symbol(b, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 16, 27)) + + c: () => "hello", +>c : Symbol(c, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 17, 23)) + + d: () => "hello", +>d : Symbol(d, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 18, 23)) + + e: () => "hello", +>e : Symbol(e, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 19, 23)) + + f: () => "hello", +>f : Symbol(f, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 20, 23)) + + g: () => "hello", +>g : Symbol(g, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 21, 23)) + + h: () => "hello", +>h : Symbol(h, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 22, 23)) + + i: () => "hello", +>i : Symbol(i, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 23, 23)) + + j: () => "hello", +>j : Symbol(j, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 24, 23)) + + k: () => 123 +>k : Symbol(k, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate.ts, 25, 23)) + } + } diff --git a/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.types b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.types new file mode 100644 index 00000000000..9cee2e8483c --- /dev/null +++ b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate.types @@ -0,0 +1,98 @@ +=== tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts === +interface Stuff { + a?: () => Promise; +>a : () => Promise + + b: () => Promise; +>b : () => Promise + + c: () => Promise; +>c : () => Promise + + d: () => Promise; +>d : () => Promise + + e: () => Promise; +>e : () => Promise + + f: () => Promise; +>f : () => Promise + + g: () => Promise; +>g : () => Promise + + h: () => Promise; +>h : () => Promise + + i: () => Promise; +>i : () => Promise + + j: () => Promise; +>j : () => Promise + + k: () => Promise; +>k : () => Promise + } + + function foo(): Stuff | string { +>foo : () => string | Stuff + + return { +>{ a() { return [123] }, b: () => "hello", c: () => "hello", d: () => "hello", e: () => "hello", f: () => "hello", g: () => "hello", h: () => "hello", i: () => "hello", j: () => "hello", k: () => 123 } : { a(): number[]; b: () => string; c: () => string; d: () => string; e: () => string; f: () => string; g: () => string; h: () => string; i: () => string; j: () => string; k: () => number; } + + a() { return [123] }, +>a : () => number[] +>[123] : number[] +>123 : 123 + + b: () => "hello", +>b : () => string +>() => "hello" : () => string +>"hello" : "hello" + + c: () => "hello", +>c : () => string +>() => "hello" : () => string +>"hello" : "hello" + + d: () => "hello", +>d : () => string +>() => "hello" : () => string +>"hello" : "hello" + + e: () => "hello", +>e : () => string +>() => "hello" : () => string +>"hello" : "hello" + + f: () => "hello", +>f : () => string +>() => "hello" : () => string +>"hello" : "hello" + + g: () => "hello", +>g : () => string +>() => "hello" : () => string +>"hello" : "hello" + + h: () => "hello", +>h : () => string +>() => "hello" : () => string +>"hello" : "hello" + + i: () => "hello", +>i : () => string +>() => "hello" : () => string +>"hello" : "hello" + + j: () => "hello", +>j : () => string +>() => "hello" : () => string +>"hello" : "hello" + + k: () => 123 +>k : () => number +>() => 123 : () => number +>123 : 123 + } + } diff --git a/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.errors.txt b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.errors.txt new file mode 100644 index 00000000000..694a367bf9b --- /dev/null +++ b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.errors.txt @@ -0,0 +1,77 @@ +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(17,5): error TS2322: Type '() => number[]' is not assignable to type '() => Promise'. + Type 'number[]' is missing the following properties from type 'Promise': then, catch +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(18,14): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(19,14): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(20,14): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(21,14): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(22,14): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(23,14): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(24,14): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(25,14): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(26,14): error TS2322: Type 'string' is not assignable to type 'Promise'. +tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts(27,14): error TS2322: Type 'number' is not assignable to type 'Promise'. + + +==== tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts (11 errors) ==== + interface Stuff { + a?: () => Promise; + b: () => Promise; + c: () => Promise; + d: () => Promise; + e: () => Promise; + f: () => Promise; + g: () => Promise; + h: () => Promise; + i: () => Promise; + j: () => Promise; + k: () => Promise; + } + + function foo(): Stuff | Date { + return { + a() { return [123] }, + ~ +!!! error TS2322: Type '() => number[]' is not assignable to type '() => Promise'. +!!! error TS2322: Type 'number[]' is missing the following properties from type 'Promise': then, catch + b: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:3:6: The expected type comes from the return type of this signature. + c: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:4:6: The expected type comes from the return type of this signature. + d: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:5:6: The expected type comes from the return type of this signature. + e: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:6:6: The expected type comes from the return type of this signature. + f: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:7:6: The expected type comes from the return type of this signature. + g: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:8:6: The expected type comes from the return type of this signature. + h: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:9:6: The expected type comes from the return type of this signature. + i: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:10:6: The expected type comes from the return type of this signature. + j: () => "hello", + ~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:11:6: The expected type comes from the return type of this signature. + k: () => 123 + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'Promise'. +!!! related TS6502 tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts:12:6: The expected type comes from the return type of this signature. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.js b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.js new file mode 100644 index 00000000000..f9ae7787ab7 --- /dev/null +++ b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.js @@ -0,0 +1,47 @@ +//// [errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts] +interface Stuff { + a?: () => Promise; + b: () => Promise; + c: () => Promise; + d: () => Promise; + e: () => Promise; + f: () => Promise; + g: () => Promise; + h: () => Promise; + i: () => Promise; + j: () => Promise; + k: () => Promise; +} + +function foo(): Stuff | Date { + return { + a() { return [123] }, + b: () => "hello", + c: () => "hello", + d: () => "hello", + e: () => "hello", + f: () => "hello", + g: () => "hello", + h: () => "hello", + i: () => "hello", + j: () => "hello", + k: () => 123 + } +} + +//// [errorOnUnionVsObjectShouldDeeplyDisambiguate2.js] +function foo() { + return { + a: function () { return [123]; }, + b: function () { return "hello"; }, + c: function () { return "hello"; }, + d: function () { return "hello"; }, + e: function () { return "hello"; }, + f: function () { return "hello"; }, + g: function () { return "hello"; }, + h: function () { return "hello"; }, + i: function () { return "hello"; }, + j: function () { return "hello"; }, + k: function () { return 123; } + }; +} diff --git a/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.symbols b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.symbols new file mode 100644 index 00000000000..3da987c3f9d --- /dev/null +++ b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.symbols @@ -0,0 +1,89 @@ +=== tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts === +interface Stuff { +>Stuff : Symbol(Stuff, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 0, 0)) + + a?: () => Promise; +>a : Symbol(Stuff.a, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 0, 17)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + b: () => Promise; +>b : Symbol(Stuff.b, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 1, 30)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + c: () => Promise; +>c : Symbol(Stuff.c, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 2, 27)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + d: () => Promise; +>d : Symbol(Stuff.d, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 3, 27)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + e: () => Promise; +>e : Symbol(Stuff.e, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 4, 27)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + f: () => Promise; +>f : Symbol(Stuff.f, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 5, 27)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + g: () => Promise; +>g : Symbol(Stuff.g, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 6, 27)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + h: () => Promise; +>h : Symbol(Stuff.h, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 7, 27)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + i: () => Promise; +>i : Symbol(Stuff.i, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 8, 27)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + j: () => Promise; +>j : Symbol(Stuff.j, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 9, 27)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + k: () => Promise; +>k : Symbol(Stuff.k, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 10, 27)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) +} + +function foo(): Stuff | Date { +>foo : Symbol(foo, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 12, 1)) +>Stuff : Symbol(Stuff, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 0, 0)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + + return { + a() { return [123] }, +>a : Symbol(a, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 15, 10)) + + b: () => "hello", +>b : Symbol(b, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 16, 25)) + + c: () => "hello", +>c : Symbol(c, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 17, 21)) + + d: () => "hello", +>d : Symbol(d, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 18, 21)) + + e: () => "hello", +>e : Symbol(e, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 19, 21)) + + f: () => "hello", +>f : Symbol(f, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 20, 21)) + + g: () => "hello", +>g : Symbol(g, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 21, 21)) + + h: () => "hello", +>h : Symbol(h, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 22, 21)) + + i: () => "hello", +>i : Symbol(i, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 23, 21)) + + j: () => "hello", +>j : Symbol(j, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 24, 21)) + + k: () => 123 +>k : Symbol(k, Decl(errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts, 25, 21)) + } +} diff --git a/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.types b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.types new file mode 100644 index 00000000000..04f10965989 --- /dev/null +++ b/tests/baselines/reference/errorOnUnionVsObjectShouldDeeplyDisambiguate2.types @@ -0,0 +1,98 @@ +=== tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts === +interface Stuff { + a?: () => Promise; +>a : () => Promise + + b: () => Promise; +>b : () => Promise + + c: () => Promise; +>c : () => Promise + + d: () => Promise; +>d : () => Promise + + e: () => Promise; +>e : () => Promise + + f: () => Promise; +>f : () => Promise + + g: () => Promise; +>g : () => Promise + + h: () => Promise; +>h : () => Promise + + i: () => Promise; +>i : () => Promise + + j: () => Promise; +>j : () => Promise + + k: () => Promise; +>k : () => Promise +} + +function foo(): Stuff | Date { +>foo : () => Stuff | Date + + return { +>{ a() { return [123] }, b: () => "hello", c: () => "hello", d: () => "hello", e: () => "hello", f: () => "hello", g: () => "hello", h: () => "hello", i: () => "hello", j: () => "hello", k: () => 123 } : { a(): number[]; b: () => string; c: () => string; d: () => string; e: () => string; f: () => string; g: () => string; h: () => string; i: () => string; j: () => string; k: () => number; } + + a() { return [123] }, +>a : () => number[] +>[123] : number[] +>123 : 123 + + b: () => "hello", +>b : () => string +>() => "hello" : () => string +>"hello" : "hello" + + c: () => "hello", +>c : () => string +>() => "hello" : () => string +>"hello" : "hello" + + d: () => "hello", +>d : () => string +>() => "hello" : () => string +>"hello" : "hello" + + e: () => "hello", +>e : () => string +>() => "hello" : () => string +>"hello" : "hello" + + f: () => "hello", +>f : () => string +>() => "hello" : () => string +>"hello" : "hello" + + g: () => "hello", +>g : () => string +>() => "hello" : () => string +>"hello" : "hello" + + h: () => "hello", +>h : () => string +>() => "hello" : () => string +>"hello" : "hello" + + i: () => "hello", +>i : () => string +>() => "hello" : () => string +>"hello" : "hello" + + j: () => "hello", +>j : () => string +>() => "hello" : () => string +>"hello" : "hello" + + k: () => 123 +>k : () => number +>() => 123 : () => number +>123 : 123 + } +} diff --git a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.errors.txt b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.errors.txt index 38ae9542a40..57d30acaba9 100644 --- a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.errors.txt +++ b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.errors.txt @@ -2,9 +2,7 @@ tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(18,3): error TS2345 Type '{ a: string; b: string; }' is not assignable to type 'Foo'. Types of property 'b' are incompatible. Type 'string' is not assignable to type 'number'. -tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(19,3): error TS2345: Argument of type '{ a: string; b: string; }' is not assignable to parameter of type 'Foo | Other'. - Types of property 'b' are incompatible. - Type 'string' is not assignable to type 'number'. +tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(19,12): error TS2322: Type 'string' is not assignable to type 'number'. tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(24,5): error TS2345: Argument of type '{ a: string; b: string; }' is not assignable to parameter of type 'Bar | Other'. Object literal may only specify known properties, and 'a' does not exist in type 'Bar | Other'. tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(42,10): error TS2345: Argument of type '{ dog: string; }' is not assignable to parameter of type 'ExoticAnimal'. @@ -42,10 +40,8 @@ tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(47,10): error TS234 !!! error TS2345: Types of property 'b' are incompatible. !!! error TS2345: Type 'string' is not assignable to type 'number'. f({ a: '', b: '' }) - ~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '{ a: string; b: string; }' is not assignable to parameter of type 'Foo | Other'. -!!! error TS2345: Types of property 'b' are incompatible. -!!! error TS2345: Type 'string' is not assignable to type 'number'. + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. declare function g(x: Bar | Other): any; diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt index 0d56383ed9a..efd14c35797 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt @@ -26,15 +26,9 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(66,9): error TS2322: Type Object literal may only specify known properties, and 'b' does not exist in type 'AN'. tests/cases/compiler/excessPropertyCheckWithUnions.ts(87,5): error TS2322: Type '{ tag: "button"; type: "submit"; href: string; }' is not assignable to type 'Union'. Object literal may only specify known properties, and 'href' does not exist in type 'Button'. -tests/cases/compiler/excessPropertyCheckWithUnions.ts(107,7): error TS2322: Type '{ foo: string; }' is not assignable to type 'ObjectDataSpecification'. - Types of property 'foo' are incompatible. - Type 'string' is not assignable to type 'IValue | undefined'. -tests/cases/compiler/excessPropertyCheckWithUnions.ts(113,7): error TS2322: Type '{ a: string; }' is not assignable to type '{ [x: string]: number; } | { [x: number]: number; }'. - Types of property 'a' are incompatible. - Type 'string' is not assignable to type 'number | undefined'. -tests/cases/compiler/excessPropertyCheckWithUnions.ts(114,7): error TS2322: Type '{ a: number; c: string; }' is not assignable to type '{ [x: string]: number; } | { a: number; }'. - Types of property 'c' are incompatible. - Type 'string' is not assignable to type 'number | undefined'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(108,5): error TS2322: Type 'string' is not assignable to type 'IValue'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(113,67): error TS2322: Type 'string' is not assignable to type 'number'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(114,63): error TS2322: Type 'string' is not assignable to type 'number'. ==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (14 errors) ==== @@ -185,23 +179,17 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(114,7): error TS2322: Type const dataSpecification: ObjectDataSpecification = { // Error - ~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ foo: string; }' is not assignable to type 'ObjectDataSpecification'. -!!! error TS2322: Types of property 'foo' are incompatible. -!!! error TS2322: Type 'string' is not assignable to type 'IValue | undefined'. foo: "asdfsadffsd" + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'IValue'. }; // Repro from #34611 const obj1: { [x: string]: number } | { [x: number]: number } = { a: 'abc' }; // Error - ~~~~ -!!! error TS2322: Type '{ a: string; }' is not assignable to type '{ [x: string]: number; } | { [x: number]: number; }'. -!!! error TS2322: Types of property 'a' are incompatible. -!!! error TS2322: Type 'string' is not assignable to type 'number | undefined'. + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. const obj2: { [x: string]: number } | { a: number } = { a: 5, c: 'abc' }; // Error - ~~~~ -!!! error TS2322: Type '{ a: number; c: string; }' is not assignable to type '{ [x: string]: number; } | { a: number; }'. -!!! error TS2322: Types of property 'c' are incompatible. -!!! error TS2322: Type 'string' is not assignable to type 'number | undefined'. + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/nestedFreshLiteral.errors.txt b/tests/baselines/reference/nestedFreshLiteral.errors.txt index fc7fc897699..46829c4f483 100644 --- a/tests/baselines/reference/nestedFreshLiteral.errors.txt +++ b/tests/baselines/reference/nestedFreshLiteral.errors.txt @@ -1,7 +1,5 @@ -tests/cases/compiler/nestedFreshLiteral.ts(12,21): error TS2322: Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'. - Types of property 'prop' are incompatible. - Type '{ colour: string; }' is not assignable to type 'CSSProps'. - Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'? +tests/cases/compiler/nestedFreshLiteral.ts(12,21): error TS2322: Type '{ colour: string; }' is not assignable to type 'CSSProps'. + Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'? ==== tests/cases/compiler/nestedFreshLiteral.ts (1 errors) ==== @@ -18,9 +16,6 @@ tests/cases/compiler/nestedFreshLiteral.ts(12,21): error TS2322: Type '{ prop: { let stylen: NestedCSSProps = { nested: { prop: { colour: 'red' } } ~~~~~~~~~~~~~ -!!! error TS2322: Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'. -!!! error TS2322: Types of property 'prop' are incompatible. -!!! error TS2322: Type '{ colour: string; }' is not assignable to type 'CSSProps'. -!!! error TS2322: Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'? -!!! related TS6500 tests/cases/compiler/nestedFreshLiteral.ts:5:3: The expected type comes from property 'nested' which is declared here on type 'NestedCSSProps' +!!! error TS2322: Type '{ colour: string; }' is not assignable to type 'CSSProps'. +!!! error TS2322: Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'? } \ No newline at end of file diff --git a/tests/baselines/reference/nestedRecursiveArraysOrObjectsError01.errors.txt b/tests/baselines/reference/nestedRecursiveArraysOrObjectsError01.errors.txt index 650a808e598..8db42a231ad 100644 --- a/tests/baselines/reference/nestedRecursiveArraysOrObjectsError01.errors.txt +++ b/tests/baselines/reference/nestedRecursiveArraysOrObjectsError01.errors.txt @@ -1,14 +1,5 @@ -tests/cases/compiler/nestedRecursiveArraysOrObjectsError01.ts(10,9): error TS2322: Type '{ foo: string; jj: number; }[][][]' is not assignable to type 'Style'. - Type '{ foo: string; jj: number; }[][][]' is not assignable to type 'StyleArray'. - The types returned by 'pop()' are incompatible between these types. - Type '{ foo: string; jj: number; }[][]' is not assignable to type 'Style'. - Type '{ foo: string; jj: number; }[][]' is not assignable to type 'StyleArray'. - The types returned by 'pop()' are incompatible between these types. - Type '{ foo: string; jj: number; }[]' is not assignable to type 'Style'. - Type '{ foo: string; jj: number; }[]' is not assignable to type 'StyleArray'. - The types returned by 'pop()' are incompatible between these types. - Type '{ foo: string; jj: number; }' is not assignable to type 'Style'. - Object literal may only specify known properties, and 'jj' does not exist in type 'Style'. +tests/cases/compiler/nestedRecursiveArraysOrObjectsError01.ts(10,9): error TS2322: Type '{ foo: string; jj: number; }' is not assignable to type 'Style'. + Object literal may only specify known properties, and 'jj' does not exist in type 'Style'. ==== tests/cases/compiler/nestedRecursiveArraysOrObjectsError01.ts (1 errors) ==== @@ -23,17 +14,8 @@ tests/cases/compiler/nestedRecursiveArraysOrObjectsError01.ts(10,9): error TS232 foo: 'asdf', jj: 1 // intentional error ~~~~~ -!!! error TS2322: Type '{ foo: string; jj: number; }[][][]' is not assignable to type 'Style'. -!!! error TS2322: Type '{ foo: string; jj: number; }[][][]' is not assignable to type 'StyleArray'. -!!! error TS2322: The types returned by 'pop()' are incompatible between these types. -!!! error TS2322: Type '{ foo: string; jj: number; }[][]' is not assignable to type 'Style'. -!!! error TS2322: Type '{ foo: string; jj: number; }[][]' is not assignable to type 'StyleArray'. -!!! error TS2322: The types returned by 'pop()' are incompatible between these types. -!!! error TS2322: Type '{ foo: string; jj: number; }[]' is not assignable to type 'Style'. -!!! error TS2322: Type '{ foo: string; jj: number; }[]' is not assignable to type 'StyleArray'. -!!! error TS2322: The types returned by 'pop()' are incompatible between these types. -!!! error TS2322: Type '{ foo: string; jj: number; }' is not assignable to type 'Style'. -!!! error TS2322: Object literal may only specify known properties, and 'jj' does not exist in type 'Style'. +!!! error TS2322: Type '{ foo: string; jj: number; }' is not assignable to type 'Style'. +!!! error TS2322: Object literal may only specify known properties, and 'jj' does not exist in type 'Style'. }]] ]; diff --git a/tests/baselines/reference/nonObjectUnionNestedExcessPropertyCheck.errors.txt b/tests/baselines/reference/nonObjectUnionNestedExcessPropertyCheck.errors.txt index 55cc7ea4c91..05f50a04dcd 100644 --- a/tests/baselines/reference/nonObjectUnionNestedExcessPropertyCheck.errors.txt +++ b/tests/baselines/reference/nonObjectUnionNestedExcessPropertyCheck.errors.txt @@ -1,13 +1,9 @@ tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts(13,35): error TS2322: Type '{ INVALID_PROP_NAME: string; iconProp: string; }' is not assignable to type 'number | IProps'. Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'IProps'. -tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts(16,49): error TS2322: Type '{ nestedProp: { asdfasdf: string; }; iconProp: string; }' is not assignable to type 'number | IProps'. - Types of property 'nestedProp' are incompatible. - Type '{ asdfasdf: string; }' is not assignable to type '{ testBool?: boolean; }'. - Object literal may only specify known properties, and 'asdfasdf' does not exist in type '{ testBool?: boolean; }'. -tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts(19,56): error TS2322: Type '{ nestedProps: { INVALID_PROP_NAME: string; iconProp: string; }; }' is not assignable to type 'number | INestedProps'. - Types of property 'nestedProps' are incompatible. - Type '{ INVALID_PROP_NAME: string; iconProp: string; }' is not assignable to type 'IProps'. - Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'IProps'. +tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts(16,49): error TS2322: Type '{ asdfasdf: string; }' is not assignable to type '{ testBool?: boolean; }'. + Object literal may only specify known properties, and 'asdfasdf' does not exist in type '{ testBool?: boolean; }'. +tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts(19,56): error TS2322: Type '{ INVALID_PROP_NAME: string; iconProp: string; }' is not assignable to type 'IProps'. + Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'IProps'. ==== tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts (3 errors) ==== @@ -31,16 +27,12 @@ tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts(19,56): error TS // Nested typing works here and we also get an expected error: const propB2: IProps | number = { nestedProp: { asdfasdf: 'test' }, iconProp: 'test' }; ~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ nestedProp: { asdfasdf: string; }; iconProp: string; }' is not assignable to type 'number | IProps'. -!!! error TS2322: Types of property 'nestedProp' are incompatible. -!!! error TS2322: Type '{ asdfasdf: string; }' is not assignable to type '{ testBool?: boolean; }'. -!!! error TS2322: Object literal may only specify known properties, and 'asdfasdf' does not exist in type '{ testBool?: boolean; }'. +!!! error TS2322: Type '{ asdfasdf: string; }' is not assignable to type '{ testBool?: boolean; }'. +!!! error TS2322: Object literal may only specify known properties, and 'asdfasdf' does not exist in type '{ testBool?: boolean; }'. // Want an error generated here but there isn't one. const propA1: INestedProps | number = { nestedProps: { INVALID_PROP_NAME: 'share', iconProp: 'test' } }; ~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ nestedProps: { INVALID_PROP_NAME: string; iconProp: string; }; }' is not assignable to type 'number | INestedProps'. -!!! error TS2322: Types of property 'nestedProps' are incompatible. -!!! error TS2322: Type '{ INVALID_PROP_NAME: string; iconProp: string; }' is not assignable to type 'IProps'. -!!! error TS2322: Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'IProps'. +!!! error TS2322: Type '{ INVALID_PROP_NAME: string; iconProp: string; }' is not assignable to type 'IProps'. +!!! error TS2322: Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'IProps'. \ No newline at end of file diff --git a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt index 4721cc72882..29263c36d54 100644 --- a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt +++ b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt @@ -2,11 +2,8 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(9,18): error TS2322: Type Object literal may only specify known properties, but 'forword' does not exist in type 'Book'. Did you mean to write 'foreword'? tests/cases/compiler/objectLiteralExcessProperties.ts(11,27): error TS2322: Type '{ foreward: string; }' is not assignable to type 'string | Book'. Object literal may only specify known properties, but 'foreward' does not exist in type 'Book'. Did you mean to write 'foreword'? -tests/cases/compiler/objectLiteralExcessProperties.ts(13,53): error TS2322: Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book | Book[]'. - Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book[]'. - Type '{ foreword: string; } | { forwards: string; }' is not assignable to type 'Book'. - Type '{ forwards: string; }' is not assignable to type 'Book'. - Object literal may only specify known properties, and 'forwards' does not exist in type 'Book'. +tests/cases/compiler/objectLiteralExcessProperties.ts(13,53): error TS2322: Type '{ forwards: string; }' is not assignable to type 'Book'. + Object literal may only specify known properties, and 'forwards' does not exist in type 'Book'. tests/cases/compiler/objectLiteralExcessProperties.ts(15,42): error TS2322: Type '{ foreword: string; colour: string; }' is not assignable to type 'Book & Cover'. Object literal may only specify known properties, but 'colour' does not exist in type 'Book & Cover'. Did you mean to write 'color'? tests/cases/compiler/objectLiteralExcessProperties.ts(17,26): error TS2322: Type '{ foreward: string; color: string; }' is not assignable to type 'Book & Cover'. @@ -56,11 +53,8 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(49,44): error TS2322: Type var b3: Book | (Book[]) = [{ foreword: "hello" }, { forwards: "back" }]; ~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book | Book[]'. -!!! error TS2322: Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book[]'. -!!! error TS2322: Type '{ foreword: string; } | { forwards: string; }' is not assignable to type 'Book'. -!!! error TS2322: Type '{ forwards: string; }' is not assignable to type 'Book'. -!!! error TS2322: Object literal may only specify known properties, and 'forwards' does not exist in type 'Book'. +!!! error TS2322: Type '{ forwards: string; }' is not assignable to type 'Book'. +!!! error TS2322: Object literal may only specify known properties, and 'forwards' does not exist in type 'Book'. var b4: Book & Cover = { foreword: "hi", colour: "blue" }; ~~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/objectLiteralsAgainstUnionsOfArrays01.errors.txt b/tests/baselines/reference/objectLiteralsAgainstUnionsOfArrays01.errors.txt index 2959f29bbc9..0b8d29be6b1 100644 --- a/tests/baselines/reference/objectLiteralsAgainstUnionsOfArrays01.errors.txt +++ b/tests/baselines/reference/objectLiteralsAgainstUnionsOfArrays01.errors.txt @@ -1,6 +1,4 @@ -tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts(10,5): error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'. - Types of property 'prop' are incompatible. - Type 'number' is not assignable to type 'string'. +tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts(10,12): error TS2322: Type 'number' is not assignable to type 'string'. ==== tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts (1 errors) ==== @@ -14,10 +12,7 @@ tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts(10,5): error TS232 let x: Foo[] = [ { bar: { prop: 100 } } - ~~~ -!!! error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'. -!!! error TS2322: Types of property 'prop' are incompatible. -!!! error TS2322: Type 'number' is not assignable to type 'string'. -!!! related TS6500 tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts:2:3: The expected type comes from property 'bar' which is declared here on type 'Foo' + ~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. ] \ No newline at end of file diff --git a/tests/baselines/reference/user/lodash.log b/tests/baselines/reference/user/lodash.log index 53427da62c4..3819d276082 100644 --- a/tests/baselines/reference/user/lodash.log +++ b/tests/baselines/reference/user/lodash.log @@ -392,10 +392,8 @@ node_modules/lodash/templateSettings.js(63,12): error TS2322: Type '{ escape: (s Object literal may only specify known properties, and ''escape'' does not exist in type 'Function'. node_modules/lodash/throttle.js(59,28): error TS2532: Object is possibly 'undefined'. node_modules/lodash/throttle.js(60,30): error TS2532: Object is possibly 'undefined'. -node_modules/lodash/throttle.js(62,31): error TS2345: Argument of type '{ leading: boolean; maxWait: number | undefined; trailing: boolean; }' is not assignable to parameter of type '{ leading?: boolean; maxWait?: number; trailing?: boolean; }'. - Types of property 'maxWait' are incompatible. - Type 'number | undefined' is not assignable to type 'number'. - Type 'undefined' is not assignable to type 'number'. +node_modules/lodash/throttle.js(64,5): error TS2322: Type 'number | undefined' is not assignable to type 'number'. + Type 'undefined' is not assignable to type 'number'. node_modules/lodash/toLower.js(11,21): error TS8024: JSDoc '@param' tag has name 'string', but there is no parameter with that name. node_modules/lodash/toUpper.js(11,21): error TS8024: JSDoc '@param' tag has name 'string', but there is no parameter with that name. node_modules/lodash/transform.js(46,37): error TS2554: Expected 0-1 arguments, but got 2. diff --git a/tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts b/tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts new file mode 100644 index 00000000000..2784b4c4904 --- /dev/null +++ b/tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate.ts @@ -0,0 +1,29 @@ +interface Stuff { + a?: () => Promise; + b: () => Promise; + c: () => Promise; + d: () => Promise; + e: () => Promise; + f: () => Promise; + g: () => Promise; + h: () => Promise; + i: () => Promise; + j: () => Promise; + k: () => Promise; + } + + function foo(): Stuff | string { + return { + a() { return [123] }, + b: () => "hello", + c: () => "hello", + d: () => "hello", + e: () => "hello", + f: () => "hello", + g: () => "hello", + h: () => "hello", + i: () => "hello", + j: () => "hello", + k: () => 123 + } + } \ No newline at end of file diff --git a/tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts b/tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts new file mode 100644 index 00000000000..f30e86f9410 --- /dev/null +++ b/tests/cases/compiler/errorOnUnionVsObjectShouldDeeplyDisambiguate2.ts @@ -0,0 +1,29 @@ +interface Stuff { + a?: () => Promise; + b: () => Promise; + c: () => Promise; + d: () => Promise; + e: () => Promise; + f: () => Promise; + g: () => Promise; + h: () => Promise; + i: () => Promise; + j: () => Promise; + k: () => Promise; +} + +function foo(): Stuff | Date { + return { + a() { return [123] }, + b: () => "hello", + c: () => "hello", + d: () => "hello", + e: () => "hello", + f: () => "hello", + g: () => "hello", + h: () => "hello", + i: () => "hello", + j: () => "hello", + k: () => 123 + } +} \ No newline at end of file