From 655496510cde1c822a4e08b1f79c8303f18a20f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 19 Jul 2022 10:24:25 +0200 Subject: [PATCH 1/4] Fixed an issue with not being able to use mapped type over union constraint as rest param --- src/compiler/checker.ts | 4 +-- ...UsingMappedTypeOverUnionConstraint.symbols | 27 +++++++++++++++++++ ...amUsingMappedTypeOverUnionConstraint.types | 18 +++++++++++++ ...ParamUsingMappedTypeOverUnionConstraint.ts | 11 ++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.symbols create mode 100644 tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types create mode 100644 tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce644034b9c3b..8915c6e8d89ce 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12318,7 +12318,7 @@ namespace ts { const typeVariable = getHomomorphicTypeVariable(type); if (typeVariable && !type.declaration.nameType) { const constraint = getConstraintOfTypeParameter(typeVariable); - if (constraint && isArrayOrTupleType(constraint)) { + if (constraint && everyType(constraint, isArrayOrTupleType)) { return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper)); } } @@ -19860,7 +19860,7 @@ namespace ts { return varianceResult; } } - else if (isReadonlyArrayType(target) ? isArrayOrTupleType(source) : isArrayType(target) && isTupleType(source) && !source.target.readonly) { + else if (isReadonlyArrayType(target) ? everyType(source, isArrayOrTupleType) : isArrayType(target) && isTupleType(source) && !source.target.readonly) { if (relation !== identityRelation) { return isRelatedTo(getIndexTypeOfType(source, numberType) || anyType, getIndexTypeOfType(target, numberType) || anyType, RecursionFlags.Both, reportErrors); } diff --git a/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.symbols b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.symbols new file mode 100644 index 0000000000000..65e90ece824cb --- /dev/null +++ b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts === +// repro 29919#issuecomment-470948453 + +type Mapped = { [P in keyof T]: T[P] extends string ? [number] : [string] } +>Mapped : Symbol(Mapped, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0)) +>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 12)) +>P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 20)) +>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 12)) +>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 12)) +>P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 20)) + +declare function test( +>test : Symbol(test, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 78)) +>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22)) + + args: T, +>args : Symbol(args, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 53)) +>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22)) + + fn: (...args: Mapped) => void +>fn : Symbol(fn, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 5, 10)) +>args : Symbol(args, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 6, 7)) +>Mapped : Symbol(Mapped, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0)) +>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22)) + +): number + diff --git a/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types new file mode 100644 index 0000000000000..1f73d493c4fce --- /dev/null +++ b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts === +// repro 29919#issuecomment-470948453 + +type Mapped = { [P in keyof T]: T[P] extends string ? [number] : [string] } +>Mapped : Mapped + +declare function test( +>test : (args: T, fn: (...args: Mapped) => void) => number + + args: T, +>args : T + + fn: (...args: Mapped) => void +>fn : (...args: Mapped) => void +>args : Mapped + +): number + diff --git a/tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts b/tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts new file mode 100644 index 0000000000000..103cc8177dbcd --- /dev/null +++ b/tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts @@ -0,0 +1,11 @@ +// @noEmit: true +// @strict: true + +// repro 29919#issuecomment-470948453 + +type Mapped = { [P in keyof T]: T[P] extends string ? [number] : [string] } + +declare function test( + args: T, + fn: (...args: Mapped) => void +): number From f94efbd493defec76f2207299a6f583979b45e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 29 Jul 2022 10:48:14 +0200 Subject: [PATCH 2/4] Fixed an issue when targeting non-readonly arrays with source being a union of tuples --- src/compiler/checker.ts | 2 +- ...onstrainTupleTreatedAsArrayLike.errors.txt | 18 ++++++++ ...onConstrainTupleTreatedAsArrayLike.symbols | 43 +++++++++++++++++++ ...nionConstrainTupleTreatedAsArrayLike.types | 35 +++++++++++++++ ...UsingMappedTypeOverUnionConstraint.symbols | 22 +++++----- ...amUsingMappedTypeOverUnionConstraint.types | 15 ++++--- ...peUnionConstrainTupleTreatedAsArrayLike.ts | 14 ++++++ ...ParamUsingMappedTypeOverUnionConstraint.ts | 6 +-- 8 files changed, 133 insertions(+), 22 deletions(-) create mode 100644 tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.errors.txt create mode 100644 tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.symbols create mode 100644 tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.types create mode 100644 tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8915c6e8d89ce..afb76b7980eba 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19860,7 +19860,7 @@ namespace ts { return varianceResult; } } - else if (isReadonlyArrayType(target) ? everyType(source, isArrayOrTupleType) : isArrayType(target) && isTupleType(source) && !source.target.readonly) { + else if (isReadonlyArrayType(target) ? everyType(source, isArrayOrTupleType) : isArrayType(target) && everyType(source, t => isTupleType(t) && !t.target.readonly)) { if (relation !== identityRelation) { return isRelatedTo(getIndexTypeOfType(source, numberType) || anyType, getIndexTypeOfType(target, numberType) || anyType, RecursionFlags.Both, reportErrors); } diff --git a/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.errors.txt b/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.errors.txt new file mode 100644 index 0000000000000..177f381f11906 --- /dev/null +++ b/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.errors.txt @@ -0,0 +1,18 @@ +tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts(9,9): error TS2322: Type 'HomomorphicMappedType' is not assignable to type 'any[]'. + + +==== tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts (1 errors) ==== + type HomomorphicMappedType = { [P in keyof T]: T[P] extends string ? boolean : null } + + function test1(args: T) { + const arr: any[] = [] as HomomorphicMappedType + const arr2: readonly any[] = [] as HomomorphicMappedType + } + + function test2(args: T) { + const arr: any[] = [] as HomomorphicMappedType // error + ~~~ +!!! error TS2322: Type 'HomomorphicMappedType' is not assignable to type 'any[]'. + const arr2: readonly any[] = [] as HomomorphicMappedType + } + \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.symbols b/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.symbols new file mode 100644 index 0000000000000..73af8f8dd924a --- /dev/null +++ b/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.symbols @@ -0,0 +1,43 @@ +=== tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts === +type HomomorphicMappedType = { [P in keyof T]: T[P] extends string ? boolean : null } +>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 27)) +>P : Symbol(P, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 35)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 27)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 27)) +>P : Symbol(P, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 35)) + +function test1(args: T) { +>test1 : Symbol(test1, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 88)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15)) +>args : Symbol(args, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 46)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15)) + + const arr: any[] = [] as HomomorphicMappedType +>arr : Symbol(arr, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 3, 7)) +>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15)) + + const arr2: readonly any[] = [] as HomomorphicMappedType +>arr2 : Symbol(arr2, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 4, 7)) +>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15)) +} + +function test2(args: T) { +>test2 : Symbol(test2, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 5, 1)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15)) +>args : Symbol(args, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 55)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15)) + + const arr: any[] = [] as HomomorphicMappedType // error +>arr : Symbol(arr, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 8, 7)) +>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15)) + + const arr2: readonly any[] = [] as HomomorphicMappedType +>arr2 : Symbol(arr2, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 9, 7)) +>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15)) +} + diff --git a/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.types b/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.types new file mode 100644 index 0000000000000..f15959a333392 --- /dev/null +++ b/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts === +type HomomorphicMappedType = { [P in keyof T]: T[P] extends string ? boolean : null } +>HomomorphicMappedType : HomomorphicMappedType +>null : null + +function test1(args: T) { +>test1 : (args: T) => void +>args : T + + const arr: any[] = [] as HomomorphicMappedType +>arr : any[] +>[] as HomomorphicMappedType : HomomorphicMappedType +>[] : [] + + const arr2: readonly any[] = [] as HomomorphicMappedType +>arr2 : readonly any[] +>[] as HomomorphicMappedType : HomomorphicMappedType +>[] : [] +} + +function test2(args: T) { +>test2 : (args: T) => void +>args : T + + const arr: any[] = [] as HomomorphicMappedType // error +>arr : any[] +>[] as HomomorphicMappedType : HomomorphicMappedType +>[] : [] + + const arr2: readonly any[] = [] as HomomorphicMappedType +>arr2 : readonly any[] +>[] as HomomorphicMappedType : HomomorphicMappedType +>[] : [] +} + diff --git a/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.symbols b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.symbols index 65e90ece824cb..1fa2ee66c7789 100644 --- a/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.symbols +++ b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.symbols @@ -1,27 +1,27 @@ === tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts === // repro 29919#issuecomment-470948453 -type Mapped = { [P in keyof T]: T[P] extends string ? [number] : [string] } ->Mapped : Symbol(Mapped, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0)) ->T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 12)) ->P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 20)) ->T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 12)) ->T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 12)) ->P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 20)) +type HomomorphicMappedType = { [P in keyof T]: T[P] extends string ? boolean : null } +>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0)) +>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 27)) +>P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 35)) +>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 27)) +>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 27)) +>P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 35)) declare function test( ->test : Symbol(test, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 78)) +>test : Symbol(test, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 88)) >T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22)) args: T, >args : Symbol(args, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 53)) >T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22)) - fn: (...args: Mapped) => void + fn: (...args: HomomorphicMappedType) => void >fn : Symbol(fn, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 5, 10)) >args : Symbol(args, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 6, 7)) ->Mapped : Symbol(Mapped, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0)) +>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0)) >T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22)) -): number +): void diff --git a/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types index 1f73d493c4fce..14da41a160ef3 100644 --- a/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types +++ b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types @@ -1,18 +1,19 @@ === tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts === // repro 29919#issuecomment-470948453 -type Mapped = { [P in keyof T]: T[P] extends string ? [number] : [string] } ->Mapped : Mapped +type HomomorphicMappedType = { [P in keyof T]: T[P] extends string ? boolean : null } +>HomomorphicMappedType : HomomorphicMappedType +>null : null declare function test( ->test : (args: T, fn: (...args: Mapped) => void) => number +>test : (args: T, fn: (...args: HomomorphicMappedType) => void) => void args: T, >args : T - fn: (...args: Mapped) => void ->fn : (...args: Mapped) => void ->args : Mapped + fn: (...args: HomomorphicMappedType) => void +>fn : (...args: HomomorphicMappedType) => void +>args : HomomorphicMappedType -): number +): void diff --git a/tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts b/tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts new file mode 100644 index 0000000000000..51e30a9fdc45b --- /dev/null +++ b/tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts @@ -0,0 +1,14 @@ +// @noEmit: true +// @strict: true + +type HomomorphicMappedType = { [P in keyof T]: T[P] extends string ? boolean : null } + +function test1(args: T) { + const arr: any[] = [] as HomomorphicMappedType + const arr2: readonly any[] = [] as HomomorphicMappedType +} + +function test2(args: T) { + const arr: any[] = [] as HomomorphicMappedType // error + const arr2: readonly any[] = [] as HomomorphicMappedType +} diff --git a/tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts b/tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts index 103cc8177dbcd..c58b0278511fc 100644 --- a/tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts +++ b/tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts @@ -3,9 +3,9 @@ // repro 29919#issuecomment-470948453 -type Mapped = { [P in keyof T]: T[P] extends string ? [number] : [string] } +type HomomorphicMappedType = { [P in keyof T]: T[P] extends string ? boolean : null } declare function test( args: T, - fn: (...args: Mapped) => void -): number + fn: (...args: HomomorphicMappedType) => void +): void From 940e1adc260c292f339aae156423a70936c1faad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sun, 19 Mar 2023 13:29:33 +0100 Subject: [PATCH 3/4] Bring back resolving apparent type for mapped types with tuple constraints but avoid resolving the apparent type of mapped types for contextual types --- src/compiler/checker.ts | 12 ++++++++++-- ...edTypeUnionConstrainTupleTreatedAsArrayLike.types | 1 - ...restParamUsingMappedTypeOverUnionConstraint.types | 1 - 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 44053da1d607c..33c554f96d6b6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13861,7 +13861,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeVariable = getHomomorphicTypeVariable(type); if (typeVariable && !type.declaration.nameType) { const constraint = getConstraintOfTypeParameter(typeVariable); - if (constraint && everyType(constraint, isArrayType)) { + if (constraint && everyType(constraint, isArrayOrTupleType)) { return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper)); } } @@ -29205,7 +29205,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getContextualType(node, contextFlags); const instantiatedType = instantiateContextualType(contextualType, node, contextFlags); if (instantiatedType && !(contextFlags && contextFlags & ContextFlags.NoConstraints && instantiatedType.flags & TypeFlags.TypeVariable)) { - const apparentType = mapType(instantiatedType, getApparentType, /*noReductions*/ true); + const apparentType = mapType( + instantiatedType, + // When obtaining apparent type of *contextual* type we don't want to get apparent type of mapped types. + // That would evaluate mapped types with array or tuple type constraints too eagerly + // and thus it would prevent `getTypeOfPropertyOfContextualType` from obtaining per-position contextual type for elements of array literal expressions. + // Apparent type of other mapped types is already the mapped type itself so we can just avoid calling `getApparentType` here for all mapped types. + t => getObjectFlags(t) & ObjectFlags.Mapped ? t : getApparentType(t), + /*noReductions*/ true + ); return apparentType.flags & TypeFlags.Union && isObjectLiteralExpression(node) ? discriminateContextualTypeByObjectMembers(node, apparentType as UnionType) : apparentType.flags & TypeFlags.Union && isJsxAttributes(node) ? discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType) : apparentType; diff --git a/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.types b/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.types index f15959a333392..cb1afa4b87d80 100644 --- a/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.types +++ b/tests/baselines/reference/mappedTypeUnionConstrainTupleTreatedAsArrayLike.types @@ -1,7 +1,6 @@ === tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts === type HomomorphicMappedType = { [P in keyof T]: T[P] extends string ? boolean : null } >HomomorphicMappedType : HomomorphicMappedType ->null : null function test1(args: T) { >test1 : (args: T) => void diff --git a/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types index 14da41a160ef3..8630f15deb77a 100644 --- a/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types +++ b/tests/baselines/reference/restParamUsingMappedTypeOverUnionConstraint.types @@ -3,7 +3,6 @@ type HomomorphicMappedType = { [P in keyof T]: T[P] extends string ? boolean : null } >HomomorphicMappedType : HomomorphicMappedType ->null : null declare function test( >test : (args: T, fn: (...args: HomomorphicMappedType) => void) => void From 8e7841437c8bac36fe691b8a650779ef0b3ec8c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 20 Mar 2023 13:37:30 +0100 Subject: [PATCH 4/4] Add extra test cases --- ...edTypeTupleConstraintAssignability.symbols | 134 ++++++++++++++++++ ...ppedTypeTupleConstraintAssignability.types | 76 ++++++++++ .../mappedTypeTupleConstraintAssignability.ts | 43 ++++++ 3 files changed, 253 insertions(+) create mode 100644 tests/baselines/reference/mappedTypeTupleConstraintAssignability.symbols create mode 100644 tests/baselines/reference/mappedTypeTupleConstraintAssignability.types create mode 100644 tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts diff --git a/tests/baselines/reference/mappedTypeTupleConstraintAssignability.symbols b/tests/baselines/reference/mappedTypeTupleConstraintAssignability.symbols new file mode 100644 index 0000000000000..c2bd5da2420ce --- /dev/null +++ b/tests/baselines/reference/mappedTypeTupleConstraintAssignability.symbols @@ -0,0 +1,134 @@ +=== tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts === +// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390594 + +type Writeable = { -readonly [P in keyof T]: T[P] }; +>Writeable : Symbol(Writeable, Decl(mappedTypeTupleConstraintAssignability.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 15)) +>P : Symbol(P, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 33)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 15)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 15)) +>P : Symbol(P, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 33)) + +type EnumValues = [string, ...string[]]; +>EnumValues : Symbol(EnumValues, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 55)) + +type Values = { [k in T[number]]: k; }; +>Values : Symbol(Values, Decl(mappedTypeTupleConstraintAssignability.ts, 3, 40)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 12)) +>EnumValues : Symbol(EnumValues, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 55)) +>k : Symbol(k, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 39)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 12)) +>k : Symbol(k, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 39)) + +declare class ZodEnum { +>ZodEnum : Symbol(ZodEnum, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 61)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 6, 22)) + + get enum(): Values +>enum : Symbol(ZodEnum.enum, Decl(mappedTypeTupleConstraintAssignability.ts, 6, 56)) +>Values : Symbol(Values, Decl(mappedTypeTupleConstraintAssignability.ts, 3, 40)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 6, 22)) +} + +declare function createZodEnum>(values: T): ZodEnum>; +>createZodEnum : Symbol(createZodEnum, Decl(mappedTypeTupleConstraintAssignability.ts, 8, 1)) +>U : Symbol(U, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 31)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 48)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>U : Symbol(U, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 31)) +>U : Symbol(U, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 31)) +>values : Symbol(values, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 82)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 48)) +>ZodEnum : Symbol(ZodEnum, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 61)) +>Writeable : Symbol(Writeable, Decl(mappedTypeTupleConstraintAssignability.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 48)) + +// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390607 + +type Maybe = T | null | undefined; +>Maybe : Symbol(Maybe, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 116)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 11)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 11)) + +type AnyTuple = [unknown, ...unknown[]]; +>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37)) + +type AnyObject = { [k: string]: any }; +>AnyObject : Symbol(AnyObject, Decl(mappedTypeTupleConstraintAssignability.ts, 15, 40)) +>k : Symbol(k, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 20)) + +type Flags = "s" | "d" | ""; +>Flags : Symbol(Flags, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 38)) + +interface ISchema { +>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 18)) +>C : Symbol(C, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 20)) +>F : Symbol(F, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 29)) +>Flags : Symbol(Flags, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 38)) +>D : Symbol(D, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 52)) + + __flags: F; +>__flags : Symbol(ISchema.__flags, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 63)) +>F : Symbol(F, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 29)) + + __context: C; +>__context : Symbol(ISchema.__context, Decl(mappedTypeTupleConstraintAssignability.ts, 20, 13)) +>C : Symbol(C, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 20)) + + __outputType: T; +>__outputType : Symbol(ISchema.__outputType, Decl(mappedTypeTupleConstraintAssignability.ts, 21, 15)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 18)) + + __default: D; +>__default : Symbol(ISchema.__default, Decl(mappedTypeTupleConstraintAssignability.ts, 22, 18)) +>D : Symbol(D, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 52)) +} + +declare class TupleSchema< +>TupleSchema : Symbol(TupleSchema, Decl(mappedTypeTupleConstraintAssignability.ts, 24, 1)) + + TType extends Maybe = AnyTuple | undefined, +>TType : Symbol(TType, Decl(mappedTypeTupleConstraintAssignability.ts, 26, 26)) +>Maybe : Symbol(Maybe, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 116)) +>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37)) +>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37)) + + TContext = AnyObject, +>TContext : Symbol(TContext, Decl(mappedTypeTupleConstraintAssignability.ts, 27, 55)) +>AnyObject : Symbol(AnyObject, Decl(mappedTypeTupleConstraintAssignability.ts, 15, 40)) + + TDefault = undefined, +>TDefault : Symbol(TDefault, Decl(mappedTypeTupleConstraintAssignability.ts, 28, 23)) + + TFlags extends Flags = "" +>TFlags : Symbol(TFlags, Decl(mappedTypeTupleConstraintAssignability.ts, 29, 23)) +>Flags : Symbol(Flags, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 38)) + +> { + constructor(schemas: [ISchema, ...ISchema[]]); +>schemas : Symbol(schemas, Decl(mappedTypeTupleConstraintAssignability.ts, 32, 14)) +>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28)) +>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28)) +} + +export function create(schemas: { +>create : Symbol(create, Decl(mappedTypeTupleConstraintAssignability.ts, 33, 1)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23)) +>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37)) +>schemas : Symbol(schemas, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 43)) + + [K in keyof T]: ISchema; +>K : Symbol(K, Decl(mappedTypeTupleConstraintAssignability.ts, 36, 3)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23)) +>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23)) +>K : Symbol(K, Decl(mappedTypeTupleConstraintAssignability.ts, 36, 3)) + +}) { + return new TupleSchema(schemas); +>TupleSchema : Symbol(TupleSchema, Decl(mappedTypeTupleConstraintAssignability.ts, 24, 1)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23)) +>schemas : Symbol(schemas, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 43)) +} + diff --git a/tests/baselines/reference/mappedTypeTupleConstraintAssignability.types b/tests/baselines/reference/mappedTypeTupleConstraintAssignability.types new file mode 100644 index 0000000000000..ae3c60e654a04 --- /dev/null +++ b/tests/baselines/reference/mappedTypeTupleConstraintAssignability.types @@ -0,0 +1,76 @@ +=== tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts === +// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390594 + +type Writeable = { -readonly [P in keyof T]: T[P] }; +>Writeable : Writeable + +type EnumValues = [string, ...string[]]; +>EnumValues : [string, ...string[]] + +type Values = { [k in T[number]]: k; }; +>Values : Values + +declare class ZodEnum { +>ZodEnum : ZodEnum + + get enum(): Values +>enum : Values +} + +declare function createZodEnum>(values: T): ZodEnum>; +>createZodEnum : (values: T) => ZodEnum> +>values : T + +// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390607 + +type Maybe = T | null | undefined; +>Maybe : Maybe + +type AnyTuple = [unknown, ...unknown[]]; +>AnyTuple : [unknown, ...unknown[]] + +type AnyObject = { [k: string]: any }; +>AnyObject : { [k: string]: any; } +>k : string + +type Flags = "s" | "d" | ""; +>Flags : "" | "s" | "d" + +interface ISchema { + __flags: F; +>__flags : F + + __context: C; +>__context : C + + __outputType: T; +>__outputType : T + + __default: D; +>__default : D +} + +declare class TupleSchema< +>TupleSchema : TupleSchema + + TType extends Maybe = AnyTuple | undefined, + TContext = AnyObject, + TDefault = undefined, + TFlags extends Flags = "" +> { + constructor(schemas: [ISchema, ...ISchema[]]); +>schemas : [ISchema, ...ISchema[]] +} + +export function create(schemas: { +>create : (schemas: { [K in keyof T]: ISchema; }) => TupleSchema +>schemas : { [K in keyof T]: ISchema; } + + [K in keyof T]: ISchema; +}) { + return new TupleSchema(schemas); +>new TupleSchema(schemas) : TupleSchema +>TupleSchema : typeof TupleSchema +>schemas : { [K in keyof T]: ISchema; } +} + diff --git a/tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts b/tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts new file mode 100644 index 0000000000000..b99300c909d9c --- /dev/null +++ b/tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts @@ -0,0 +1,43 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390594 + +type Writeable = { -readonly [P in keyof T]: T[P] }; +type EnumValues = [string, ...string[]]; +type Values = { [k in T[number]]: k; }; + +declare class ZodEnum { + get enum(): Values +} + +declare function createZodEnum>(values: T): ZodEnum>; + +// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390607 + +type Maybe = T | null | undefined; +type AnyTuple = [unknown, ...unknown[]]; +type AnyObject = { [k: string]: any }; +type Flags = "s" | "d" | ""; + +interface ISchema { + __flags: F; + __context: C; + __outputType: T; + __default: D; +} + +declare class TupleSchema< + TType extends Maybe = AnyTuple | undefined, + TContext = AnyObject, + TDefault = undefined, + TFlags extends Flags = "" +> { + constructor(schemas: [ISchema, ...ISchema[]]); +} + +export function create(schemas: { + [K in keyof T]: ISchema; +}) { + return new TupleSchema(schemas); +}