Merge pull request #26895 from Microsoft/callableErrors
Find first callable/constructable type in union when appropriate
This commit is contained in:
commit
cf2f339a5c
|
@ -11441,7 +11441,8 @@ namespace ts {
|
|||
const bestMatchingType =
|
||||
findMatchingDiscriminantType(source, target) ||
|
||||
findMatchingTypeReferenceOrTypeAliasReference(source, target) ||
|
||||
findBestTypeForObjectLiteral(source, target);
|
||||
findBestTypeForObjectLiteral(source, target) ||
|
||||
findBestTypeForInvokable(source, target);
|
||||
|
||||
isRelatedTo(source, bestMatchingType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true);
|
||||
}
|
||||
|
@ -11472,6 +11473,15 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly
|
||||
function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) {
|
||||
let match: Type | undefined;
|
||||
|
|
|
@ -22,9 +22,9 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(
|
|||
Type 'string | number' is not assignable to type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(58,5): error TS2322: Type '(a: string, b: number) => string | number' is not assignable to type '((a: string, b: number) => string) | ((a: string, b: number) => number)'.
|
||||
Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => number'.
|
||||
Type 'string | number' is not assignable to type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => string'.
|
||||
Type 'string | number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts (6 errors) ====
|
||||
|
@ -116,8 +116,8 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(
|
|||
commonMethodDifferentReturnType: (a, b) => strOrNumber,
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '(a: string, b: number) => string | number' is not assignable to type '((a: string, b: number) => string) | ((a: string, b: number) => number)'.
|
||||
!!! error TS2322: Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => number'.
|
||||
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
!!! error TS2322: Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => string'.
|
||||
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! related TS6500 tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts:35:5: The expected type comes from property 'commonMethodDifferentReturnType' which is declared here on type 'I11 | I21'
|
||||
};
|
|
@ -0,0 +1,40 @@
|
|||
tests/cases/compiler/errorsWithInvokablesInUnions01.ts(14,12): error TS2322: Type '(x: string) => void' is not assignable to type 'ConstructableA | IDirectiveLinkFn<number> | IDirectivePrePost<number>'.
|
||||
Type '(x: string) => void' is not assignable to type 'IDirectiveLinkFn<number>'.
|
||||
Types of parameters 'x' and 'scope' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/compiler/errorsWithInvokablesInUnions01.ts(16,12): error TS2322: Type 'typeof ctor' is not assignable to type 'ConstructableA | IDirectiveLinkFn<number> | IDirectivePrePost<number>'.
|
||||
Type 'typeof ctor' is not assignable to type 'ConstructableA'.
|
||||
Type 'ctor' is not assignable to type '{ somePropA: any; }'.
|
||||
Property 'somePropA' is missing in type 'ctor'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/errorsWithInvokablesInUnions01.ts (2 errors) ====
|
||||
interface ConstructableA {
|
||||
new(): { somePropA: any };
|
||||
}
|
||||
|
||||
interface IDirectiveLinkFn<TScope> {
|
||||
(scope: TScope): void;
|
||||
}
|
||||
|
||||
interface IDirectivePrePost<TScope> {
|
||||
pre?: IDirectiveLinkFn<TScope>;
|
||||
post?: IDirectiveLinkFn<TScope>;
|
||||
}
|
||||
|
||||
export let blah: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = (x: string) => {}
|
||||
~~~~
|
||||
!!! error TS2322: Type '(x: string) => void' is not assignable to type 'ConstructableA | IDirectiveLinkFn<number> | IDirectivePrePost<number>'.
|
||||
!!! error TS2322: Type '(x: string) => void' is not assignable to type 'IDirectiveLinkFn<number>'.
|
||||
!!! error TS2322: Types of parameters 'x' and 'scope' are incompatible.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
export let ctor: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = class {
|
||||
~~~~
|
||||
!!! error TS2322: Type 'typeof ctor' is not assignable to type 'ConstructableA | IDirectiveLinkFn<number> | IDirectivePrePost<number>'.
|
||||
!!! error TS2322: Type 'typeof ctor' is not assignable to type 'ConstructableA'.
|
||||
!!! error TS2322: Type 'ctor' is not assignable to type '{ somePropA: any; }'.
|
||||
!!! error TS2322: Property 'somePropA' is missing in type 'ctor'.
|
||||
someUnaccountedProp: any;
|
||||
}
|
||||
|
30
tests/baselines/reference/errorsWithInvokablesInUnions01.js
Normal file
30
tests/baselines/reference/errorsWithInvokablesInUnions01.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
//// [errorsWithInvokablesInUnions01.ts]
|
||||
interface ConstructableA {
|
||||
new(): { somePropA: any };
|
||||
}
|
||||
|
||||
interface IDirectiveLinkFn<TScope> {
|
||||
(scope: TScope): void;
|
||||
}
|
||||
|
||||
interface IDirectivePrePost<TScope> {
|
||||
pre?: IDirectiveLinkFn<TScope>;
|
||||
post?: IDirectiveLinkFn<TScope>;
|
||||
}
|
||||
|
||||
export let blah: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = (x: string) => {}
|
||||
|
||||
export let ctor: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = class {
|
||||
someUnaccountedProp: any;
|
||||
}
|
||||
|
||||
|
||||
//// [errorsWithInvokablesInUnions01.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.blah = function (x) { };
|
||||
exports.ctor = /** @class */ (function () {
|
||||
function class_1() {
|
||||
}
|
||||
return class_1;
|
||||
}());
|
|
@ -0,0 +1,49 @@
|
|||
=== tests/cases/compiler/errorsWithInvokablesInUnions01.ts ===
|
||||
interface ConstructableA {
|
||||
>ConstructableA : Symbol(ConstructableA, Decl(errorsWithInvokablesInUnions01.ts, 0, 0))
|
||||
|
||||
new(): { somePropA: any };
|
||||
>somePropA : Symbol(somePropA, Decl(errorsWithInvokablesInUnions01.ts, 1, 10))
|
||||
}
|
||||
|
||||
interface IDirectiveLinkFn<TScope> {
|
||||
>IDirectiveLinkFn : Symbol(IDirectiveLinkFn, Decl(errorsWithInvokablesInUnions01.ts, 2, 1))
|
||||
>TScope : Symbol(TScope, Decl(errorsWithInvokablesInUnions01.ts, 4, 27))
|
||||
|
||||
(scope: TScope): void;
|
||||
>scope : Symbol(scope, Decl(errorsWithInvokablesInUnions01.ts, 5, 5))
|
||||
>TScope : Symbol(TScope, Decl(errorsWithInvokablesInUnions01.ts, 4, 27))
|
||||
}
|
||||
|
||||
interface IDirectivePrePost<TScope> {
|
||||
>IDirectivePrePost : Symbol(IDirectivePrePost, Decl(errorsWithInvokablesInUnions01.ts, 6, 1))
|
||||
>TScope : Symbol(TScope, Decl(errorsWithInvokablesInUnions01.ts, 8, 28))
|
||||
|
||||
pre?: IDirectiveLinkFn<TScope>;
|
||||
>pre : Symbol(IDirectivePrePost.pre, Decl(errorsWithInvokablesInUnions01.ts, 8, 37))
|
||||
>IDirectiveLinkFn : Symbol(IDirectiveLinkFn, Decl(errorsWithInvokablesInUnions01.ts, 2, 1))
|
||||
>TScope : Symbol(TScope, Decl(errorsWithInvokablesInUnions01.ts, 8, 28))
|
||||
|
||||
post?: IDirectiveLinkFn<TScope>;
|
||||
>post : Symbol(IDirectivePrePost.post, Decl(errorsWithInvokablesInUnions01.ts, 9, 35))
|
||||
>IDirectiveLinkFn : Symbol(IDirectiveLinkFn, Decl(errorsWithInvokablesInUnions01.ts, 2, 1))
|
||||
>TScope : Symbol(TScope, Decl(errorsWithInvokablesInUnions01.ts, 8, 28))
|
||||
}
|
||||
|
||||
export let blah: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = (x: string) => {}
|
||||
>blah : Symbol(blah, Decl(errorsWithInvokablesInUnions01.ts, 13, 10))
|
||||
>IDirectiveLinkFn : Symbol(IDirectiveLinkFn, Decl(errorsWithInvokablesInUnions01.ts, 2, 1))
|
||||
>ConstructableA : Symbol(ConstructableA, Decl(errorsWithInvokablesInUnions01.ts, 0, 0))
|
||||
>IDirectivePrePost : Symbol(IDirectivePrePost, Decl(errorsWithInvokablesInUnions01.ts, 6, 1))
|
||||
>x : Symbol(x, Decl(errorsWithInvokablesInUnions01.ts, 13, 90))
|
||||
|
||||
export let ctor: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = class {
|
||||
>ctor : Symbol(ctor, Decl(errorsWithInvokablesInUnions01.ts, 15, 10))
|
||||
>IDirectiveLinkFn : Symbol(IDirectiveLinkFn, Decl(errorsWithInvokablesInUnions01.ts, 2, 1))
|
||||
>ConstructableA : Symbol(ConstructableA, Decl(errorsWithInvokablesInUnions01.ts, 0, 0))
|
||||
>IDirectivePrePost : Symbol(IDirectivePrePost, Decl(errorsWithInvokablesInUnions01.ts, 6, 1))
|
||||
|
||||
someUnaccountedProp: any;
|
||||
>someUnaccountedProp : Symbol(ctor.someUnaccountedProp, Decl(errorsWithInvokablesInUnions01.ts, 15, 96))
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
=== tests/cases/compiler/errorsWithInvokablesInUnions01.ts ===
|
||||
interface ConstructableA {
|
||||
new(): { somePropA: any };
|
||||
>somePropA : any
|
||||
}
|
||||
|
||||
interface IDirectiveLinkFn<TScope> {
|
||||
(scope: TScope): void;
|
||||
>scope : TScope
|
||||
}
|
||||
|
||||
interface IDirectivePrePost<TScope> {
|
||||
pre?: IDirectiveLinkFn<TScope>;
|
||||
>pre : IDirectiveLinkFn<TScope>
|
||||
|
||||
post?: IDirectiveLinkFn<TScope>;
|
||||
>post : IDirectiveLinkFn<TScope>
|
||||
}
|
||||
|
||||
export let blah: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = (x: string) => {}
|
||||
>blah : ConstructableA | IDirectiveLinkFn<number> | IDirectivePrePost<number>
|
||||
>(x: string) => {} : (x: string) => void
|
||||
>x : string
|
||||
|
||||
export let ctor: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = class {
|
||||
>ctor : ConstructableA | IDirectiveLinkFn<number> | IDirectivePrePost<number>
|
||||
>class { someUnaccountedProp: any;} : typeof ctor
|
||||
|
||||
someUnaccountedProp: any;
|
||||
>someUnaccountedProp : any
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping2.ts(11,1): error TS2322: Type '(foo: number, bar: string) => boolean' is not assignable to type '((n: number, s: string) => number) | ((n: number, s: string) => string)'.
|
||||
Type '(foo: number, bar: string) => boolean' is not assignable to type '(n: number, s: string) => string'.
|
||||
Type 'boolean' is not assignable to type 'string'.
|
||||
Type '(foo: number, bar: string) => boolean' is not assignable to type '(n: number, s: string) => number'.
|
||||
Type 'boolean' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping2.ts (1 errors) ====
|
||||
|
@ -17,5 +17,5 @@ tests/cases/conformance/expressions/contextualTyping/functionExpressionContextua
|
|||
a1 = (foo, bar) => { return true; } // Error
|
||||
~~
|
||||
!!! error TS2322: Type '(foo: number, bar: string) => boolean' is not assignable to type '((n: number, s: string) => number) | ((n: number, s: string) => string)'.
|
||||
!!! error TS2322: Type '(foo: number, bar: string) => boolean' is not assignable to type '(n: number, s: string) => string'.
|
||||
!!! error TS2322: Type 'boolean' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type '(foo: number, bar: string) => boolean' is not assignable to type '(n: number, s: string) => number'.
|
||||
!!! error TS2322: Type 'boolean' is not assignable to type 'number'.
|
18
tests/cases/compiler/errorsWithInvokablesInUnions01.ts
Normal file
18
tests/cases/compiler/errorsWithInvokablesInUnions01.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
interface ConstructableA {
|
||||
new(): { somePropA: any };
|
||||
}
|
||||
|
||||
interface IDirectiveLinkFn<TScope> {
|
||||
(scope: TScope): void;
|
||||
}
|
||||
|
||||
interface IDirectivePrePost<TScope> {
|
||||
pre?: IDirectiveLinkFn<TScope>;
|
||||
post?: IDirectiveLinkFn<TScope>;
|
||||
}
|
||||
|
||||
export let blah: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = (x: string) => {}
|
||||
|
||||
export let ctor: IDirectiveLinkFn<number> | ConstructableA | IDirectivePrePost<number> = class {
|
||||
someUnaccountedProp: any;
|
||||
}
|
Loading…
Reference in a new issue