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对相同的情况应用不同的策略?