inferTypeArguments

이 함수에서 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 호출 위의 코드를 호출 된다

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 를 호출해서 contextcandidate 에 추가한다.TypeVariabletype candidate 를 추가한다.

가장 기본적인 흐름이다.

예제 1

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 로 추가된다.