Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19321,7 +19321,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

function isDistributionDependent(root: ConditionalRoot) {
return root.isDistributive && (
return root.isDistributive && !(root.extendsType.flags & TypeFlags.AnyOrUnknown) && (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't correct as it removes those correct errors:

function f5<T>(t1: { x: T; y: T }, t2: T extends any ? { x: T; y: T } : never) {
  t1 = t2; // OK
  t2 = t1; // should fail
}

function f6<T>(t1: { x: T; y: T }, t2: T extends unknown ? { x: T; y: T } : never) {
  t1 = t2; // OK
  t2 = t1; // should fail
}

isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.trueType) ||
isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.falseType)
);
Expand Down Expand Up @@ -23206,7 +23206,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const c = target as ConditionalType;
// We check for a relationship to a conditional type target only when the conditional type has no
// 'infer' positions, is not distributive or is distributive but doesn't reference the check type
// parameter in either of the result types, and the source isn't an instantiation of the same
// parameter in either of the result types, and extends type is other than unknown or any, and the source isn't an instantiation of the same
// conditional type (as happens when computing variance).
if (!c.root.inferTypeParameters && !isDistributionDependent(c.root) && !(source.flags & TypeFlags.Conditional && (source as ConditionalType).root === c.root)) {
// Check if the conditional is always true or always false but still deferred for distribution purposes.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//// [tests/cases/compiler/conditionalTypeAssignabilityWithSimpleDistribution1.ts] ////

=== conditionalTypeAssignabilityWithSimpleDistribution1.ts ===
type AllKeys<T> = T extends unknown ? keyof T : never;
>AllKeys : Symbol(AllKeys, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 0, 0))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 0, 13))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 0, 13))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 0, 13))

type WithKeyOfConstraint<T, K extends keyof T> = unknown;
>WithKeyOfConstraint : Symbol(WithKeyOfConstraint, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 0, 54))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 2, 25))
>K : Symbol(K, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 2, 27))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 2, 25))

type Test1<T> = WithKeyOfConstraint<T, AllKeys<T>>; // ok
>Test1 : Symbol(Test1, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 2, 57))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 3, 11))
>WithKeyOfConstraint : Symbol(WithKeyOfConstraint, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 0, 54))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 3, 11))
>AllKeys : Symbol(AllKeys, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 0, 0))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 3, 11))

type WithAllKeysConstraint<T, K extends AllKeys<T>> = unknown;
>WithAllKeysConstraint : Symbol(WithAllKeysConstraint, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 3, 51))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 5, 27))
>K : Symbol(K, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 5, 29))
>AllKeys : Symbol(AllKeys, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 0, 0))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 5, 27))

type Test2<T> = WithAllKeysConstraint<T, keyof T>; // ok
>Test2 : Symbol(Test2, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 5, 62))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 6, 11))
>WithAllKeysConstraint : Symbol(WithAllKeysConstraint, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 3, 51))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 6, 11))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 6, 11))

declare function test3<T>(
>test3 : Symbol(test3, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 6, 50))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 8, 23))

p1: T,
>p1 : Symbol(p1, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 8, 26))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 8, 23))

p2: T extends unknown ? T & { css?: unknown } : never,
>p2 : Symbol(p2, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 9, 8))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 8, 23))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 8, 23))
>css : Symbol(css, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 10, 31))

): void;

const wrapper = <P extends object>(props: P) => {
>wrapper : Symbol(wrapper, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 13, 5))
>P : Symbol(P, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 13, 17))
>props : Symbol(props, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 13, 35))
>P : Symbol(P, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 13, 17))

test3(
>test3 : Symbol(test3, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 6, 50))

props,
>props : Symbol(props, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 13, 35))

props, // ok
>props : Symbol(props, Decl(conditionalTypeAssignabilityWithSimpleDistribution1.ts, 13, 35))

);
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//// [tests/cases/compiler/conditionalTypeAssignabilityWithSimpleDistribution1.ts] ////

=== conditionalTypeAssignabilityWithSimpleDistribution1.ts ===
type AllKeys<T> = T extends unknown ? keyof T : never;
>AllKeys : AllKeys<T>
> : ^^^^^^^^^^

type WithKeyOfConstraint<T, K extends keyof T> = unknown;
>WithKeyOfConstraint : unknown
> : ^^^^^^^

type Test1<T> = WithKeyOfConstraint<T, AllKeys<T>>; // ok
>Test1 : unknown
> : ^^^^^^^

type WithAllKeysConstraint<T, K extends AllKeys<T>> = unknown;
>WithAllKeysConstraint : unknown
> : ^^^^^^^

type Test2<T> = WithAllKeysConstraint<T, keyof T>; // ok
>Test2 : unknown
> : ^^^^^^^

declare function test3<T>(
>test3 : <T>(p1: T, p2: T extends unknown ? T & { css?: unknown; } : never) => void
> : ^ ^^ ^^ ^^ ^^ ^^^^^

p1: T,
>p1 : T
> : ^

p2: T extends unknown ? T & { css?: unknown } : never,
>p2 : T extends unknown ? T & { css?: unknown; } : never
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^
>css : unknown
> : ^^^^^^^

): void;

const wrapper = <P extends object>(props: P) => {
>wrapper : <P extends object>(props: P) => void
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^
><P extends object>(props: P) => { test3( props, props, // ok );} : <P extends object>(props: P) => void
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^
>props : P
> : ^

test3(
>test3( props, props, // ok ) : void
> : ^^^^
>test3 : <T>(p1: T, p2: T extends unknown ? T & { css?: unknown; } : never) => void
> : ^ ^^ ^^ ^^ ^^ ^^^^^

props,
>props : P
> : ^

props, // ok
>props : P
> : ^

);
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//// [tests/cases/compiler/conditionalTypeAssignabilityWithSimpleDistribution2.ts] ////

=== conditionalTypeAssignabilityWithSimpleDistribution2.ts ===
type AllKeys<T> = T extends any ? keyof T : never;
>AllKeys : Symbol(AllKeys, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 0, 0))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 0, 13))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 0, 13))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 0, 13))

type WithKeyOfConstraint<T, K extends keyof T> = unknown;
>WithKeyOfConstraint : Symbol(WithKeyOfConstraint, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 0, 50))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 2, 25))
>K : Symbol(K, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 2, 27))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 2, 25))

type Test1<T> = WithKeyOfConstraint<T, AllKeys<T>>; // ok
>Test1 : Symbol(Test1, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 2, 57))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 3, 11))
>WithKeyOfConstraint : Symbol(WithKeyOfConstraint, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 0, 50))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 3, 11))
>AllKeys : Symbol(AllKeys, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 0, 0))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 3, 11))

type WithAllKeysConstraint<T, K extends AllKeys<T>> = unknown;
>WithAllKeysConstraint : Symbol(WithAllKeysConstraint, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 3, 51))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 5, 27))
>K : Symbol(K, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 5, 29))
>AllKeys : Symbol(AllKeys, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 0, 0))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 5, 27))

type Test2<T> = WithAllKeysConstraint<T, keyof T>; // ok
>Test2 : Symbol(Test2, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 5, 62))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 6, 11))
>WithAllKeysConstraint : Symbol(WithAllKeysConstraint, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 3, 51))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 6, 11))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 6, 11))

declare function test3<T>(
>test3 : Symbol(test3, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 6, 50))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 8, 23))

p1: T,
>p1 : Symbol(p1, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 8, 26))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 8, 23))

p2: T extends any ? T & { css?: unknown } : never,
>p2 : Symbol(p2, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 9, 8))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 8, 23))
>T : Symbol(T, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 8, 23))
>css : Symbol(css, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 10, 27))

): void;

const wrapper = <P extends object>(props: P) => {
>wrapper : Symbol(wrapper, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 13, 5))
>P : Symbol(P, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 13, 17))
>props : Symbol(props, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 13, 35))
>P : Symbol(P, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 13, 17))

test3(
>test3 : Symbol(test3, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 6, 50))

props,
>props : Symbol(props, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 13, 35))

props, // ok
>props : Symbol(props, Decl(conditionalTypeAssignabilityWithSimpleDistribution2.ts, 13, 35))

);
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//// [tests/cases/compiler/conditionalTypeAssignabilityWithSimpleDistribution2.ts] ////

=== conditionalTypeAssignabilityWithSimpleDistribution2.ts ===
type AllKeys<T> = T extends any ? keyof T : never;
>AllKeys : AllKeys<T>
> : ^^^^^^^^^^

type WithKeyOfConstraint<T, K extends keyof T> = unknown;
>WithKeyOfConstraint : unknown
> : ^^^^^^^

type Test1<T> = WithKeyOfConstraint<T, AllKeys<T>>; // ok
>Test1 : unknown
> : ^^^^^^^

type WithAllKeysConstraint<T, K extends AllKeys<T>> = unknown;
>WithAllKeysConstraint : unknown
> : ^^^^^^^

type Test2<T> = WithAllKeysConstraint<T, keyof T>; // ok
>Test2 : unknown
> : ^^^^^^^

declare function test3<T>(
>test3 : <T>(p1: T, p2: T extends any ? T & { css?: unknown; } : never) => void
> : ^ ^^ ^^ ^^ ^^ ^^^^^

p1: T,
>p1 : T
> : ^

p2: T extends any ? T & { css?: unknown } : never,
>p2 : T extends any ? T & { css?: unknown; } : never
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^
>css : unknown
> : ^^^^^^^

): void;

const wrapper = <P extends object>(props: P) => {
>wrapper : <P extends object>(props: P) => void
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^
><P extends object>(props: P) => { test3( props, props, // ok );} : <P extends object>(props: P) => void
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^
>props : P
> : ^

test3(
>test3( props, props, // ok ) : void
> : ^^^^
>test3 : <T>(p1: T, p2: T extends any ? T & { css?: unknown; } : never) => void
> : ^ ^^ ^^ ^^ ^^ ^^^^^

props,
>props : P
> : ^

props, // ok
>props : P
> : ^

);
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// @strict: true
// @noEmit: true

type AllKeys<T> = T extends unknown ? keyof T : never;

type WithKeyOfConstraint<T, K extends keyof T> = unknown;
type Test1<T> = WithKeyOfConstraint<T, AllKeys<T>>; // ok

type WithAllKeysConstraint<T, K extends AllKeys<T>> = unknown;
type Test2<T> = WithAllKeysConstraint<T, keyof T>; // ok

declare function test3<T>(
p1: T,
p2: T extends unknown ? T & { css?: unknown } : never,
): void;

const wrapper = <P extends object>(props: P) => {
test3(
props,
props, // ok
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// @strict: true
// @noEmit: true

type AllKeys<T> = T extends any ? keyof T : never;

type WithKeyOfConstraint<T, K extends keyof T> = unknown;
type Test1<T> = WithKeyOfConstraint<T, AllKeys<T>>; // ok

type WithAllKeysConstraint<T, K extends AllKeys<T>> = unknown;
type Test2<T> = WithAllKeysConstraint<T, keyof T>; // ok

declare function test3<T>(
p1: T,
p2: T extends any ? T & { css?: unknown } : never,
): void;

const wrapper = <P extends object>(props: P) => {
test3(
props,
props, // ok
);
};
Loading