Only skip any checks for unwrapped tuples in conditionals, rather than all nondistributive conditionals for backcompat (#42447)
This commit is contained in:
parent
9dbfaeef2d
commit
2730cb24f5
|
@ -14647,6 +14647,7 @@ namespace ts {
|
|||
// types of the form 'A extends B ? X : C extends D ? Y : E extends F ? Z : ...' as a single construct for
|
||||
// purposes of resolution. This means such types aren't subject to the instatiation depth limiter.
|
||||
while (true) {
|
||||
const isUnwrapped = isTypicalNondistributiveConditional(root);
|
||||
const checkType = instantiateType(unwrapNondistributiveConditionalTuple(root, root.checkType), mapper);
|
||||
const checkTypeInstantiable = isGenericObjectType(checkType) || isGenericIndexType(checkType);
|
||||
const extendsType = instantiateType(unwrapNondistributiveConditionalTuple(root, root.extendsType), mapper);
|
||||
|
@ -14672,9 +14673,9 @@ namespace ts {
|
|||
// types with type parameters mapped to the wildcard type, the most permissive instantiations
|
||||
// possible (the wildcard type is assignable to and from all types). If those are not related,
|
||||
// then no instantiations will be and we can just return the false branch type.
|
||||
if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && ((checkType.flags & TypeFlags.Any && root.isDistributive) || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) {
|
||||
if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && ((checkType.flags & TypeFlags.Any && !isUnwrapped) || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) {
|
||||
// Return union of trueType and falseType for 'any' since it matches anything
|
||||
if (checkType.flags & TypeFlags.Any && root.isDistributive) {
|
||||
if (checkType.flags & TypeFlags.Any && !isUnwrapped) {
|
||||
(extraTypes || (extraTypes = [])).push(instantiateType(getTypeFromTypeNode(root.node.trueType), combinedMapper || mapper));
|
||||
}
|
||||
// If falseType is an immediately nested conditional type that isn't distributive or has an
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
tests/cases/compiler/conditionalAnyCheckTypePicksBothBranches.ts(9,1): error TS2322: Type '0' is not assignable to type '1'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/conditionalAnyCheckTypePicksBothBranches.ts (1 errors) ====
|
||||
type T = any extends number ? 1 : 0;
|
||||
let x: T;
|
||||
x = 1;
|
||||
x = 0; // not an error
|
||||
|
||||
type U = [any] extends [number] ? 1 : 0;
|
||||
let y: U;
|
||||
y = 1;
|
||||
y = 0; // error
|
||||
~
|
||||
!!! error TS2322: Type '0' is not assignable to type '1'.
|
|
@ -0,0 +1,18 @@
|
|||
//// [conditionalAnyCheckTypePicksBothBranches.ts]
|
||||
type T = any extends number ? 1 : 0;
|
||||
let x: T;
|
||||
x = 1;
|
||||
x = 0; // not an error
|
||||
|
||||
type U = [any] extends [number] ? 1 : 0;
|
||||
let y: U;
|
||||
y = 1;
|
||||
y = 0; // error
|
||||
|
||||
//// [conditionalAnyCheckTypePicksBothBranches.js]
|
||||
var x;
|
||||
x = 1;
|
||||
x = 0; // not an error
|
||||
var y;
|
||||
y = 1;
|
||||
y = 0; // error
|
|
@ -0,0 +1,27 @@
|
|||
=== tests/cases/compiler/conditionalAnyCheckTypePicksBothBranches.ts ===
|
||||
type T = any extends number ? 1 : 0;
|
||||
>T : Symbol(T, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 0, 0))
|
||||
|
||||
let x: T;
|
||||
>x : Symbol(x, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 1, 3))
|
||||
>T : Symbol(T, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 0, 0))
|
||||
|
||||
x = 1;
|
||||
>x : Symbol(x, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 1, 3))
|
||||
|
||||
x = 0; // not an error
|
||||
>x : Symbol(x, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 1, 3))
|
||||
|
||||
type U = [any] extends [number] ? 1 : 0;
|
||||
>U : Symbol(U, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 3, 6))
|
||||
|
||||
let y: U;
|
||||
>y : Symbol(y, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 6, 3))
|
||||
>U : Symbol(U, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 3, 6))
|
||||
|
||||
y = 1;
|
||||
>y : Symbol(y, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 6, 3))
|
||||
|
||||
y = 0; // error
|
||||
>y : Symbol(y, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 6, 3))
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
=== tests/cases/compiler/conditionalAnyCheckTypePicksBothBranches.ts ===
|
||||
type T = any extends number ? 1 : 0;
|
||||
>T : 0 | 1
|
||||
|
||||
let x: T;
|
||||
>x : 0 | 1
|
||||
|
||||
x = 1;
|
||||
>x = 1 : 1
|
||||
>x : 0 | 1
|
||||
>1 : 1
|
||||
|
||||
x = 0; // not an error
|
||||
>x = 0 : 0
|
||||
>x : 0 | 1
|
||||
>0 : 0
|
||||
|
||||
type U = [any] extends [number] ? 1 : 0;
|
||||
>U : 1
|
||||
|
||||
let y: U;
|
||||
>y : 1
|
||||
|
||||
y = 1;
|
||||
>y = 1 : 1
|
||||
>y : 1
|
||||
>1 : 1
|
||||
|
||||
y = 0; // error
|
||||
>y = 0 : 0
|
||||
>y : 1
|
||||
>0 : 0
|
||||
|
|
@ -257,7 +257,7 @@ type T61<T> = infer A extends infer B ? infer C : infer D; // Error
|
|||
>T61 : T61<T>
|
||||
|
||||
type T62<T> = U extends (infer U)[] ? U : U; // Error
|
||||
>T62 : unknown
|
||||
>T62 : any
|
||||
|
||||
type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
|
||||
>T63 : T63<T>
|
||||
|
|
|
@ -105,7 +105,7 @@ type TT3 = TupleOf<number, any>;
|
|||
>TT3 : number[]
|
||||
|
||||
type TT4 = TupleOf<number, 100>; // Depth error
|
||||
>TT4 : [any, ...any[]]
|
||||
>TT4 : any
|
||||
|
||||
function f22<N extends number, M extends N>(tn: TupleOf<number, N>, tm: TupleOf<number, M>) {
|
||||
>f22 : <N extends number, M extends N>(tn: TupleOf<number, N>, tm: TupleOf<number, M>) => void
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
type T = any extends number ? 1 : 0;
|
||||
let x: T;
|
||||
x = 1;
|
||||
x = 0; // not an error
|
||||
|
||||
type U = [any] extends [number] ? 1 : 0;
|
||||
let y: U;
|
||||
y = 1;
|
||||
y = 0; // error
|
Loading…
Reference in a new issue