이 함수에서 context 에 candidate 를 넣는다.
function inferTypeArguments(node: CallLikeExpression, ..., context: InferenceContext): Type[] {
// in inferTypeArguments
for (let i = 0; i < argCount; i++) {
const arg = args[i];
if (arg.kind !== SyntaxKind.OmittedExpression) {
const paramType = getTypeAtPosition(signature, i);
if (couldContainTypeVariables(paramType)) {
const argType = checkExpressionWithContextualType(
arg,
paramType,
context,
checkMode
);
inferTypes(context.inferences, argType, paramType);
}
}
}
inferTypes 호출 위의 코드를 호출 된다
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type){
...
function inferFromTypes(source: Type, target: Type): void {
...
if (target.flags & TypeFlags.Union)
...
if (target.flags & TypeFlags.TypeVariable){
...
inference.contraCandidates = append(inference.contraCandidates, candidate);
}
}
}
inferTypes는 source 와 target 의 타입들을 분해해서 inferFromTypes를 재귀적으로 호출한다.
만약 object type 일경우 inferFromObjectTypes ⇒ inferFromProperties, inferFromSignatures, inferFromIndexTypes inferFromProperties 에서는 inferFromTypes 에 source, target 의 Property 들을 inferFromTypes 넣어서 호출한다.
최종적으로는 targe type 이 TypeVariable이 될떄까지 분해하고 append 를 호출해서 context 의 candidate 에 추가한다.TypeVariable 에 type candidate 를 추가한다.
가장 기본적인 흐름이다.
CallLikeExpression 일때 infer argement 을 해서 node: CallLikeExpression 을 arg 로 호출
function identity<T>(value: T): T {
return value;
}
identity({ a : 1 })
identity({ a : 1 }) 를 호출하게 되면 T 에는 { a : number } ( { a : 1} 이 아님을 유의)이 candidate 로 추가된다.