Allow untyped calls on unions of untyped things (#29265)
This commit is contained in:
parent
4a0bc59f77
commit
19c72c758a
5 changed files with 122 additions and 3 deletions
|
@ -6930,7 +6930,7 @@ namespace ts {
|
|||
function resolveUnionTypeMembers(type: UnionType) {
|
||||
// The members and properties collections are empty for union types. To get all properties of a union
|
||||
// type use getPropertiesOfType (only the language service uses this).
|
||||
const callSignatures = getUnionSignatures(map(type.types, t => getSignaturesOfType(t, SignatureKind.Call)));
|
||||
const callSignatures = getUnionSignatures(map(type.types, t => t === globalFunctionType ? [unknownSignature] : getSignaturesOfType(t, SignatureKind.Call)));
|
||||
const constructSignatures = getUnionSignatures(map(type.types, t => getSignaturesOfType(t, SignatureKind.Construct)));
|
||||
const stringIndexInfo = getUnionIndexInfo(type.types, IndexKind.String);
|
||||
const numberIndexInfo = getUnionIndexInfo(type.types, IndexKind.Number);
|
||||
|
@ -20506,9 +20506,9 @@ namespace ts {
|
|||
* If FuncExpr is of type Any, or of an object type that has no call or construct signatures
|
||||
* but is a subtype of the Function interface, the call is an untyped function call.
|
||||
*/
|
||||
function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number) {
|
||||
function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number): boolean {
|
||||
// We exclude union types because we may have a union of function types that happen to have no common signatures.
|
||||
return isTypeAny(funcType) || isTypeAny(apparentFuncType) && funcType.flags & TypeFlags.TypeParameter ||
|
||||
return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & TypeFlags.TypeParameter) ||
|
||||
!numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (TypeFlags.Union | TypeFlags.Never)) && isTypeAssignableTo(funcType, globalFunctionType);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
//// [unionOfFunctionAndSignatureIsCallable.ts]
|
||||
function f1(c1: Function, c2: () => object, callable: typeof c1 | typeof c2) {
|
||||
const a = c1();
|
||||
const b = c2();
|
||||
const c = callable();
|
||||
}
|
||||
|
||||
function f2(fetcherParams: object | (() => object)) {
|
||||
const data = typeof fetcherParams === 'function'
|
||||
? fetcherParams()
|
||||
: fetcherParams
|
||||
}
|
||||
|
||||
|
||||
//// [unionOfFunctionAndSignatureIsCallable.js]
|
||||
function f1(c1, c2, callable) {
|
||||
var a = c1();
|
||||
var b = c2();
|
||||
var c = callable();
|
||||
}
|
||||
function f2(fetcherParams) {
|
||||
var data = typeof fetcherParams === 'function'
|
||||
? fetcherParams()
|
||||
: fetcherParams;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
=== tests/cases/compiler/unionOfFunctionAndSignatureIsCallable.ts ===
|
||||
function f1(c1: Function, c2: () => object, callable: typeof c1 | typeof c2) {
|
||||
>f1 : Symbol(f1, Decl(unionOfFunctionAndSignatureIsCallable.ts, 0, 0))
|
||||
>c1 : Symbol(c1, Decl(unionOfFunctionAndSignatureIsCallable.ts, 0, 12))
|
||||
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>c2 : Symbol(c2, Decl(unionOfFunctionAndSignatureIsCallable.ts, 0, 25))
|
||||
>callable : Symbol(callable, Decl(unionOfFunctionAndSignatureIsCallable.ts, 0, 43))
|
||||
>c1 : Symbol(c1, Decl(unionOfFunctionAndSignatureIsCallable.ts, 0, 12))
|
||||
>c2 : Symbol(c2, Decl(unionOfFunctionAndSignatureIsCallable.ts, 0, 25))
|
||||
|
||||
const a = c1();
|
||||
>a : Symbol(a, Decl(unionOfFunctionAndSignatureIsCallable.ts, 1, 9))
|
||||
>c1 : Symbol(c1, Decl(unionOfFunctionAndSignatureIsCallable.ts, 0, 12))
|
||||
|
||||
const b = c2();
|
||||
>b : Symbol(b, Decl(unionOfFunctionAndSignatureIsCallable.ts, 2, 9))
|
||||
>c2 : Symbol(c2, Decl(unionOfFunctionAndSignatureIsCallable.ts, 0, 25))
|
||||
|
||||
const c = callable();
|
||||
>c : Symbol(c, Decl(unionOfFunctionAndSignatureIsCallable.ts, 3, 9))
|
||||
>callable : Symbol(callable, Decl(unionOfFunctionAndSignatureIsCallable.ts, 0, 43))
|
||||
}
|
||||
|
||||
function f2(fetcherParams: object | (() => object)) {
|
||||
>f2 : Symbol(f2, Decl(unionOfFunctionAndSignatureIsCallable.ts, 4, 1))
|
||||
>fetcherParams : Symbol(fetcherParams, Decl(unionOfFunctionAndSignatureIsCallable.ts, 6, 12))
|
||||
|
||||
const data = typeof fetcherParams === 'function'
|
||||
>data : Symbol(data, Decl(unionOfFunctionAndSignatureIsCallable.ts, 7, 9))
|
||||
>fetcherParams : Symbol(fetcherParams, Decl(unionOfFunctionAndSignatureIsCallable.ts, 6, 12))
|
||||
|
||||
? fetcherParams()
|
||||
>fetcherParams : Symbol(fetcherParams, Decl(unionOfFunctionAndSignatureIsCallable.ts, 6, 12))
|
||||
|
||||
: fetcherParams
|
||||
>fetcherParams : Symbol(fetcherParams, Decl(unionOfFunctionAndSignatureIsCallable.ts, 6, 12))
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
=== tests/cases/compiler/unionOfFunctionAndSignatureIsCallable.ts ===
|
||||
function f1(c1: Function, c2: () => object, callable: typeof c1 | typeof c2) {
|
||||
>f1 : (c1: Function, c2: () => object, callable: Function | (() => object)) => void
|
||||
>c1 : Function
|
||||
>c2 : () => object
|
||||
>callable : Function | (() => object)
|
||||
>c1 : Function
|
||||
>c2 : () => object
|
||||
|
||||
const a = c1();
|
||||
>a : any
|
||||
>c1() : any
|
||||
>c1 : Function
|
||||
|
||||
const b = c2();
|
||||
>b : object
|
||||
>c2() : object
|
||||
>c2 : () => object
|
||||
|
||||
const c = callable();
|
||||
>c : any
|
||||
>callable() : any
|
||||
>callable : Function | (() => object)
|
||||
}
|
||||
|
||||
function f2(fetcherParams: object | (() => object)) {
|
||||
>f2 : (fetcherParams: object | (() => object)) => void
|
||||
>fetcherParams : object | (() => object)
|
||||
|
||||
const data = typeof fetcherParams === 'function'
|
||||
>data : any
|
||||
>typeof fetcherParams === 'function' ? fetcherParams() : fetcherParams : any
|
||||
>typeof fetcherParams === 'function' : boolean
|
||||
>typeof fetcherParams : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>fetcherParams : object | (() => object)
|
||||
>'function' : "function"
|
||||
|
||||
? fetcherParams()
|
||||
>fetcherParams() : any
|
||||
>fetcherParams : Function | (() => object)
|
||||
|
||||
: fetcherParams
|
||||
>fetcherParams : object
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
function f1(c1: Function, c2: () => object, callable: typeof c1 | typeof c2) {
|
||||
const a = c1();
|
||||
const b = c2();
|
||||
const c = callable();
|
||||
}
|
||||
|
||||
function f2(fetcherParams: object | (() => object)) {
|
||||
const data = typeof fetcherParams === 'function'
|
||||
? fetcherParams()
|
||||
: fetcherParams
|
||||
}
|
Loading…
Reference in a new issue