diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f315b1a75cc..529f78fdc96 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21583,6 +21583,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, RecursionFlags.Source, reportErrors && constraint !== unknownType && !(targetFlags & sourceFlags & TypeFlags.TypeParameter), /*headMessage*/ undefined, intersectionState)) { return result; } + if (sourceFlags & TypeFlags.IndexedAccess) { + const indexType = (source as IndexedAccessType).indexType; + if (indexType.flags & TypeFlags.Index) { + const unresolvedIndexConstraint = getBaseConstraintOfType((indexType as IndexType).type); + const indexConstraint = unresolvedIndexConstraint && unresolvedIndexConstraint !== noConstraintType ? getIndexType(unresolvedIndexConstraint) : keyofConstraintType; + const constraint = getIndexedAccessType((source as IndexedAccessType).objectType, indexConstraint); + if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) { + return result; + } + } + } if (isMappedTypeGenericIndexedAccess(source)) { // For an indexed access type { [P in K]: E}[X], above we have already explored an instantiation of E with X // substituted for P. We also want to explore type { [P in K]: E }[C], where C is the constraint of X. diff --git a/tests/baselines/reference/constraintWithIndexedAccess.errors.txt b/tests/baselines/reference/constraintWithIndexedAccess.errors.txt new file mode 100644 index 00000000000..f8a8539b9b2 --- /dev/null +++ b/tests/baselines/reference/constraintWithIndexedAccess.errors.txt @@ -0,0 +1,60 @@ +tests/cases/compiler/constraintWithIndexedAccess.ts(28,102): error TS2344: Type 'DataFetchFns[T][T]' does not satisfy the constraint '(...args: any) => any'. + Type 'DataFetchFns[T]["Boat"] | DataFetchFns[T]["Plane"]' is not assignable to type '(...args: any) => any'. + Type 'DataFetchFns[T]["Boat"]' is not assignable to type '(...args: any) => any'. +tests/cases/compiler/constraintWithIndexedAccess.ts(28,102): error TS2536: Type 'T' cannot be used to index type 'DataFetchFns[T]'. +tests/cases/compiler/constraintWithIndexedAccess.ts(29,102): error TS2536: Type 'F' cannot be used to index type 'DataFetchFns'. +tests/cases/compiler/constraintWithIndexedAccess.ts(29,102): error TS2344: Type 'DataFetchFns[F][F]' does not satisfy the constraint '(...args: any) => any'. + Type 'DataFetchFns[F][keyof DataFetchFns[T]]' is not assignable to type '(...args: any) => any'. + Type 'DataFetchFns[F][string] | DataFetchFns[F][number] | DataFetchFns[F][symbol]' is not assignable to type '(...args: any) => any'. + Type 'DataFetchFns[F][string]' is not assignable to type '(...args: any) => any'. + Type 'DataFetchFns[keyof DataFetchFns[T]][string]' is not assignable to type '(...args: any) => any'. +tests/cases/compiler/constraintWithIndexedAccess.ts(29,102): error TS2536: Type 'F' cannot be used to index type 'DataFetchFns[F]'. + + +==== tests/cases/compiler/constraintWithIndexedAccess.ts (5 errors) ==== + // #52399 + type DataFetchFns = { + Boat: { + requiresLicense: (id: string) => boolean; + maxGroundSpeed: (id: string) => number; + description: (id: string) => string; + displacement: (id: string) => number; + name: (id: string) => string; + }; + Plane: { + requiresLicense: (id: string) => boolean; + maxGroundSpeed: (id: string) => number; + maxTakeoffWeight: (id: string) => number; + maxCruisingAltitude: (id: string) => number; + name: (id: string) => string; + } + } + export type NoTypeParamBoatRequired = ReturnType; + type TypeHardcodedAsParameterWithoutReturnType = DataFetchFns[T][F]; + export type allAreFunctionsAsExpected = TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>; + export type returnTypeOfFunctions = ReturnType; //string | number | boolean as expected + export type SucceedingCombo = ReturnType>; + export type FailingCombo = ReturnType>; + export type TypeHardcodedAsParameter = ReturnType; + type VehicleSelector = DataFetchFns[T]; + export type TypeHardcodedAsParameter2 = ReturnType[F]>; + export type TypeGeneric1 = ReturnType; + export type TypeGeneric2 = ReturnType; // error + ~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'DataFetchFns[T][T]' does not satisfy the constraint '(...args: any) => any'. +!!! error TS2344: Type 'DataFetchFns[T]["Boat"] | DataFetchFns[T]["Plane"]' is not assignable to type '(...args: any) => any'. +!!! error TS2344: Type 'DataFetchFns[T]["Boat"]' is not assignable to type '(...args: any) => any'. + ~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'T' cannot be used to index type 'DataFetchFns[T]'. + export type TypeGeneric3 = ReturnType; // error + ~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'F' cannot be used to index type 'DataFetchFns'. + ~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'DataFetchFns[F][F]' does not satisfy the constraint '(...args: any) => any'. +!!! error TS2344: Type 'DataFetchFns[F][keyof DataFetchFns[T]]' is not assignable to type '(...args: any) => any'. +!!! error TS2344: Type 'DataFetchFns[F][string] | DataFetchFns[F][number] | DataFetchFns[F][symbol]' is not assignable to type '(...args: any) => any'. +!!! error TS2344: Type 'DataFetchFns[F][string]' is not assignable to type '(...args: any) => any'. +!!! error TS2344: Type 'DataFetchFns[keyof DataFetchFns[T]][string]' is not assignable to type '(...args: any) => any'. + ~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'F' cannot be used to index type 'DataFetchFns[F]'. + \ No newline at end of file diff --git a/tests/baselines/reference/constraintWithIndexedAccess.js b/tests/baselines/reference/constraintWithIndexedAccess.js new file mode 100644 index 00000000000..9a60445571e --- /dev/null +++ b/tests/baselines/reference/constraintWithIndexedAccess.js @@ -0,0 +1,35 @@ +//// [constraintWithIndexedAccess.ts] +// #52399 +type DataFetchFns = { + Boat: { + requiresLicense: (id: string) => boolean; + maxGroundSpeed: (id: string) => number; + description: (id: string) => string; + displacement: (id: string) => number; + name: (id: string) => string; + }; + Plane: { + requiresLicense: (id: string) => boolean; + maxGroundSpeed: (id: string) => number; + maxTakeoffWeight: (id: string) => number; + maxCruisingAltitude: (id: string) => number; + name: (id: string) => string; + } +} +export type NoTypeParamBoatRequired = ReturnType; +type TypeHardcodedAsParameterWithoutReturnType = DataFetchFns[T][F]; +export type allAreFunctionsAsExpected = TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>; +export type returnTypeOfFunctions = ReturnType; //string | number | boolean as expected +export type SucceedingCombo = ReturnType>; +export type FailingCombo = ReturnType>; +export type TypeHardcodedAsParameter = ReturnType; +type VehicleSelector = DataFetchFns[T]; +export type TypeHardcodedAsParameter2 = ReturnType[F]>; +export type TypeGeneric1 = ReturnType; +export type TypeGeneric2 = ReturnType; // error +export type TypeGeneric3 = ReturnType; // error + + +//// [constraintWithIndexedAccess.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/constraintWithIndexedAccess.symbols b/tests/baselines/reference/constraintWithIndexedAccess.symbols new file mode 100644 index 00000000000..60802dd4688 --- /dev/null +++ b/tests/baselines/reference/constraintWithIndexedAccess.symbols @@ -0,0 +1,163 @@ +=== tests/cases/compiler/constraintWithIndexedAccess.ts === +// #52399 +type DataFetchFns = { +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) + + Boat: { +>Boat : Symbol(Boat, Decl(constraintWithIndexedAccess.ts, 1, 21)) + + requiresLicense: (id: string) => boolean; +>requiresLicense : Symbol(requiresLicense, Decl(constraintWithIndexedAccess.ts, 2, 11)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 3, 26)) + + maxGroundSpeed: (id: string) => number; +>maxGroundSpeed : Symbol(maxGroundSpeed, Decl(constraintWithIndexedAccess.ts, 3, 49)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 4, 25)) + + description: (id: string) => string; +>description : Symbol(description, Decl(constraintWithIndexedAccess.ts, 4, 47)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 5, 22)) + + displacement: (id: string) => number; +>displacement : Symbol(displacement, Decl(constraintWithIndexedAccess.ts, 5, 44)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 6, 23)) + + name: (id: string) => string; +>name : Symbol(name, Decl(constraintWithIndexedAccess.ts, 6, 45)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 7, 15)) + + }; + Plane: { +>Plane : Symbol(Plane, Decl(constraintWithIndexedAccess.ts, 8, 6)) + + requiresLicense: (id: string) => boolean; +>requiresLicense : Symbol(requiresLicense, Decl(constraintWithIndexedAccess.ts, 9, 12)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 10, 26)) + + maxGroundSpeed: (id: string) => number; +>maxGroundSpeed : Symbol(maxGroundSpeed, Decl(constraintWithIndexedAccess.ts, 10, 49)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 11, 25)) + + maxTakeoffWeight: (id: string) => number; +>maxTakeoffWeight : Symbol(maxTakeoffWeight, Decl(constraintWithIndexedAccess.ts, 11, 47)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 12, 27)) + + maxCruisingAltitude: (id: string) => number; +>maxCruisingAltitude : Symbol(maxCruisingAltitude, Decl(constraintWithIndexedAccess.ts, 12, 49)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 13, 30)) + + name: (id: string) => string; +>name : Symbol(name, Decl(constraintWithIndexedAccess.ts, 13, 52)) +>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 14, 15)) + } +} +export type NoTypeParamBoatRequired = ReturnType; +>NoTypeParamBoatRequired : Symbol(NoTypeParamBoatRequired, Decl(constraintWithIndexedAccess.ts, 16, 1)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 17, 36)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 17, 36)) + +type TypeHardcodedAsParameterWithoutReturnType = DataFetchFns[T][F]; +>TypeHardcodedAsParameterWithoutReturnType : Symbol(TypeHardcodedAsParameterWithoutReturnType, Decl(constraintWithIndexedAccess.ts, 17, 112)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 18, 47)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 18, 64)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 18, 47)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 18, 47)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 18, 64)) + +export type allAreFunctionsAsExpected = TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>; +>allAreFunctionsAsExpected : Symbol(allAreFunctionsAsExpected, Decl(constraintWithIndexedAccess.ts, 18, 119)) +>TypeHardcodedAsParameterWithoutReturnType : Symbol(TypeHardcodedAsParameterWithoutReturnType, Decl(constraintWithIndexedAccess.ts, 17, 112)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) + +export type returnTypeOfFunctions = ReturnType; //string | number | boolean as expected +>returnTypeOfFunctions : Symbol(returnTypeOfFunctions, Decl(constraintWithIndexedAccess.ts, 19, 118)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>allAreFunctionsAsExpected : Symbol(allAreFunctionsAsExpected, Decl(constraintWithIndexedAccess.ts, 18, 119)) + +export type SucceedingCombo = ReturnType>; +>SucceedingCombo : Symbol(SucceedingCombo, Decl(constraintWithIndexedAccess.ts, 20, 74)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>TypeHardcodedAsParameterWithoutReturnType : Symbol(TypeHardcodedAsParameterWithoutReturnType, Decl(constraintWithIndexedAccess.ts, 17, 112)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) + +export type FailingCombo = ReturnType>; +>FailingCombo : Symbol(FailingCombo, Decl(constraintWithIndexedAccess.ts, 21, 120)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 22, 25)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 22, 42)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 22, 25)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>TypeHardcodedAsParameterWithoutReturnType : Symbol(TypeHardcodedAsParameterWithoutReturnType, Decl(constraintWithIndexedAccess.ts, 17, 112)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 22, 25)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 22, 42)) + +export type TypeHardcodedAsParameter = ReturnType; +>TypeHardcodedAsParameter : Symbol(TypeHardcodedAsParameter, Decl(constraintWithIndexedAccess.ts, 22, 137)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 23, 37)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 23, 54)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 23, 37)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 23, 37)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 23, 54)) + +type VehicleSelector = DataFetchFns[T]; +>VehicleSelector : Symbol(VehicleSelector, Decl(constraintWithIndexedAccess.ts, 23, 121)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 24, 21)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 24, 21)) + +export type TypeHardcodedAsParameter2 = ReturnType[F]>; +>TypeHardcodedAsParameter2 : Symbol(TypeHardcodedAsParameter2, Decl(constraintWithIndexedAccess.ts, 24, 69)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 25, 38)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 25, 55)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 25, 38)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>VehicleSelector : Symbol(VehicleSelector, Decl(constraintWithIndexedAccess.ts, 23, 121)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 25, 38)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 25, 55)) + +export type TypeGeneric1 = ReturnType; +>TypeGeneric1 : Symbol(TypeGeneric1, Decl(constraintWithIndexedAccess.ts, 25, 125)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 26, 25)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 26, 54)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 26, 25)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 26, 25)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 26, 54)) + +export type TypeGeneric2 = ReturnType; // error +>TypeGeneric2 : Symbol(TypeGeneric2, Decl(constraintWithIndexedAccess.ts, 26, 121)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 27, 25)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 27, 54)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 27, 25)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 27, 25)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 27, 25)) + +export type TypeGeneric3 = ReturnType; // error +>TypeGeneric3 : Symbol(TypeGeneric3, Decl(constraintWithIndexedAccess.ts, 27, 121)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 28, 25)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 28, 54)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 28, 25)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 28, 54)) +>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 28, 54)) + diff --git a/tests/baselines/reference/constraintWithIndexedAccess.types b/tests/baselines/reference/constraintWithIndexedAccess.types new file mode 100644 index 00000000000..0c236abe404 --- /dev/null +++ b/tests/baselines/reference/constraintWithIndexedAccess.types @@ -0,0 +1,89 @@ +=== tests/cases/compiler/constraintWithIndexedAccess.ts === +// #52399 +type DataFetchFns = { +>DataFetchFns : { Boat: { requiresLicense: (id: string) => boolean; maxGroundSpeed: (id: string) => number; description: (id: string) => string; displacement: (id: string) => number; name: (id: string) => string; }; Plane: { requiresLicense: (id: string) => boolean; maxGroundSpeed: (id: string) => number; maxTakeoffWeight: (id: string) => number; maxCruisingAltitude: (id: string) => number; name: (id: string) => string; }; } + + Boat: { +>Boat : { requiresLicense: (id: string) => boolean; maxGroundSpeed: (id: string) => number; description: (id: string) => string; displacement: (id: string) => number; name: (id: string) => string; } + + requiresLicense: (id: string) => boolean; +>requiresLicense : (id: string) => boolean +>id : string + + maxGroundSpeed: (id: string) => number; +>maxGroundSpeed : (id: string) => number +>id : string + + description: (id: string) => string; +>description : (id: string) => string +>id : string + + displacement: (id: string) => number; +>displacement : (id: string) => number +>id : string + + name: (id: string) => string; +>name : (id: string) => string +>id : string + + }; + Plane: { +>Plane : { requiresLicense: (id: string) => boolean; maxGroundSpeed: (id: string) => number; maxTakeoffWeight: (id: string) => number; maxCruisingAltitude: (id: string) => number; name: (id: string) => string; } + + requiresLicense: (id: string) => boolean; +>requiresLicense : (id: string) => boolean +>id : string + + maxGroundSpeed: (id: string) => number; +>maxGroundSpeed : (id: string) => number +>id : string + + maxTakeoffWeight: (id: string) => number; +>maxTakeoffWeight : (id: string) => number +>id : string + + maxCruisingAltitude: (id: string) => number; +>maxCruisingAltitude : (id: string) => number +>id : string + + name: (id: string) => string; +>name : (id: string) => string +>id : string + } +} +export type NoTypeParamBoatRequired = ReturnType; +>NoTypeParamBoatRequired : NoTypeParamBoatRequired + +type TypeHardcodedAsParameterWithoutReturnType = DataFetchFns[T][F]; +>TypeHardcodedAsParameterWithoutReturnType : TypeHardcodedAsParameterWithoutReturnType + +export type allAreFunctionsAsExpected = TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>; +>allAreFunctionsAsExpected : ((id: string) => boolean) | ((id: string) => number) | ((id: string) => string) | ((id: string) => number) | ((id: string) => string) + +export type returnTypeOfFunctions = ReturnType; //string | number | boolean as expected +>returnTypeOfFunctions : string | number | boolean + +export type SucceedingCombo = ReturnType>; +>SucceedingCombo : string | number | boolean + +export type FailingCombo = ReturnType>; +>FailingCombo : FailingCombo + +export type TypeHardcodedAsParameter = ReturnType; +>TypeHardcodedAsParameter : TypeHardcodedAsParameter + +type VehicleSelector = DataFetchFns[T]; +>VehicleSelector : VehicleSelector + +export type TypeHardcodedAsParameter2 = ReturnType[F]>; +>TypeHardcodedAsParameter2 : TypeHardcodedAsParameter2 + +export type TypeGeneric1 = ReturnType; +>TypeGeneric1 : TypeGeneric1 + +export type TypeGeneric2 = ReturnType; // error +>TypeGeneric2 : TypeGeneric2 + +export type TypeGeneric3 = ReturnType; // error +>TypeGeneric3 : TypeGeneric3 + diff --git a/tests/cases/compiler/constraintWithIndexedAccess.ts b/tests/cases/compiler/constraintWithIndexedAccess.ts new file mode 100644 index 00000000000..4b40399820c --- /dev/null +++ b/tests/cases/compiler/constraintWithIndexedAccess.ts @@ -0,0 +1,29 @@ +// #52399 +type DataFetchFns = { + Boat: { + requiresLicense: (id: string) => boolean; + maxGroundSpeed: (id: string) => number; + description: (id: string) => string; + displacement: (id: string) => number; + name: (id: string) => string; + }; + Plane: { + requiresLicense: (id: string) => boolean; + maxGroundSpeed: (id: string) => number; + maxTakeoffWeight: (id: string) => number; + maxCruisingAltitude: (id: string) => number; + name: (id: string) => string; + } +} +export type NoTypeParamBoatRequired = ReturnType; +type TypeHardcodedAsParameterWithoutReturnType = DataFetchFns[T][F]; +export type allAreFunctionsAsExpected = TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>; +export type returnTypeOfFunctions = ReturnType; //string | number | boolean as expected +export type SucceedingCombo = ReturnType>; +export type FailingCombo = ReturnType>; +export type TypeHardcodedAsParameter = ReturnType; +type VehicleSelector = DataFetchFns[T]; +export type TypeHardcodedAsParameter2 = ReturnType[F]>; +export type TypeGeneric1 = ReturnType; +export type TypeGeneric2 = ReturnType; // error +export type TypeGeneric3 = ReturnType; // error