Typescript中的上下文键入

Typescript中的上下文键入,typescript,Typescript,片段: class A { x: number; } class B extends A { y: number; } var f1: { (y: A): void } | { (y: B): void }; f1 = (y)=>{} // y :any var f2: { (x: number): (y: A) => void } | { (x: number): (y: B) => void }; f2 = ((x) => { return (y

片段:

class A {
    x: number;
}

class B extends A {
    y: number;
}

var f1: { (y: A): void } | { (y: B): void };
f1 = (y)=>{} // y :any

var f2: { (x: number): (y: A) => void } | { (x: number): (y: B) => void };
f2 = ((x) => { return (y)=>{}; }); //y :A

为什么当箭头函数由
f1
上下文输入时,
y
参数具有
any
类型,但在
f2
的情况下,
y
参数具有
A
类型?

每当上下文类型是潜在签名的联合时,所有这些签名必须完全相同。这包括参数类型

原因是,对于你可能想要的东西,它是模棱两可的。您可以想象逻辑上说“联合函数可以满足的所有签名的参数”,但这项工作尚未完成

作为一种参考,下面是我们源代码中涵盖它的部分:

function getContextualSignature(node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature {
    Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
    const type = getContextualTypeForFunctionLikeDeclaration(node);
    if (!type) {
        return undefined;
    }
    if (!(type.flags & TypeFlags.Union)) {
        return getNonGenericSignature(type, node);
    }
    let signatureList: Signature[];
    const types = (<UnionType>type).types;
    for (const current of types) {
        const signature = getNonGenericSignature(current, node);
        if (signature) {
            if (!signatureList) {
                // This signature will contribute to contextual union signature
                signatureList = [signature];
            }
            else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true, compareTypesIdentical)) {
                // Signatures aren't identical, do not use
                return undefined;
            }
            else {
                // Use this signature for contextual union signature
                signatureList.push(signature);
            }
        }
    }
function getContextualSignature(节点:FunctionExpression | ArrowFunction | MethodDeclaration):签名{
assert(node.kind!==SyntaxKind.MethodDeclaration | | isObjectLiteralMethod(node));
const type=getContextualTypeForFunctionLikeDeclaration(节点);
如果(!类型){
返回未定义;
}
if(!(type.flags和TypeFlags.Union)){
返回getNonGenericSignature(类型,节点);
}
let signatureList:签名[];
常量类型=(类型).types;
用于(当前类型的常数){
const signature=getNonGenericSignature(当前,节点);
如果(签字){
如果(!签名列表){
//此签名将有助于上下文联合签名
签名列表=[签名];
}
如果(!compareSignaturesIdentical(signatureList[0],signature,/*partialMatch*/false,/*忽略ThisTypes*/true,/*忽略ReturnTypes*/true,CompareTypesidential)){
//签名不相同,请不要使用
返回未定义;
}
否则{
//将此签名用于上下文联合签名
签名者推送(签名);
}
}
}

如果不真正查看源代码,很难回答这个问题,但无论哪种方式,都有更好的方法来键入
f1
f2
。对于
f1
var f1:(y:A | B)=>void
很高兴在stackoverflow见到您,谢谢。您提到的代码用于箭头函数,该函数由
f1
上下文键入。您提到的规则(上下文类型是潜在签名的联合,所有这些签名必须完全相同)from spec应用于
f1
。但是在
f2的情况下,返回表达式语句(箭头函数)由
{(y:A)=>void}{(y:B)=>void}上下文键入
与案例
f1
中的类型相同,但是typescript应用
getUnionType
减少了联合,结果的上下文类型是
{(y:A):void}
,为什么?两种情况下都是相同的上下文类型,但首先tsc比较参数等价性,然后使用
getUnionType
进行缩减,这是一个真正的问题,为什么typescript对相同的情况应用不同的策略?