https://github.com/microsoft/TypeScript/issues/61743

밑의 코드에서 T1, T2 의 타입이 달라서 생기는 이슈였다.

declare class X {
	private a: number;
	b: string;
}
type Y = { a: number } & { b: string };
type Z = Pick<{ a: number }, 'a'> & { b: string };
type T1 = X & Y // T1 is never
type T2 = X & Z // but T2 is not never

property 가 private 인지 확인하는 함수 *getReducedTypeisNeverReducedPropertyisConflictingPrivateProperty*

function isConflictingPrivateProperty(prop: Symbol) {
  // Return true for a synthetic property with multiple declarations, at least one of which is private.
  return (
    !prop.valueDeclaration &&
    !!(getCheckFlags(prop) & CheckFlags.ContainsPrivate)
  );
}

declare class X {
  private a: number;

}
type C = Pick<{ a: 1 }, 'a'> & X;

위의 예제는 C의 property 의 a 에 valueDeclaration 이 있어서 isConflictingPrivateProperty 의 결과가 무조건 false 로 나온다.

valueDeclaration

https://github.com/microsoft/TypeScript/pull/61346#discussion_r1980147888

Andarist 이분이 단 댓글중에 valueDeclaration 를 설명하는 댓글이 있다.

.valueDeclaration is only set on union/intersection properties when it's "uniform"(ish).

intersection이랑 union 이고 property 를 비교할때 두 property 의 valuedeclation 이 같을 경우에 valueDeclaration intersection/union 의 property 에 설정되야 한다.

intersection/union 의 property 를 설정하는 코드는 createUnionOrIntersectionProperty 이 함수에 있다. 그중에서도 firstValueDeclaration 를 설정하는 코드만 일부 뽑아왔다.

let hasNonUniformValueDeclaration = false;
for (const prop of props) {
  if (!firstValueDeclaration) {
    firstValueDeclaration = prop.valueDeclaration;
  } else if (
    prop.valueDeclaration &&
    prop.valueDeclaration !== firstValueDeclaration
  ) {
    hasNonUniformValueDeclaration = true;
  }
}

이코드를 이해하기 위해 구현되었던 pr이슈를 찾았다.

intersection/union property 를 만들때 두 심볼을 비교할때 한 쪽이 valueDeclaration이 있고 한쪽이 valueDeclaration 없을때에도 uniform 하다고 설정되고 있었다.

위의 isConflictingPrivateProperty 로직은 unifrom 하지않고 property 가 private 일때만 conflict 하다고 판단한다.