@@ -23464,7 +23464,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2346423464 return result;
2346523465 }
2346623466
23467- function getApparentMappedTypeKeys(nameType: Type, mappedType: MappedType) {
23467+ function getApparentMappedTypeKeys(nameType: Type, mappedType: MappedType, forSource: boolean ) {
2346823468 const modifiersType = getApparentType(getModifiersTypeFromMappedType(mappedType));
2346923469 const mappedKeys: Type[] = [];
2347023470 forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(
@@ -23473,7 +23473,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2347323473 /*stringsOnly*/ false,
2347423474 t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(mappedType.mapper, getTypeParameterFromMappedType(mappedType), t))),
2347523475 );
23476- return getUnionType(mappedKeys);
23476+ const apparentKeys = getUnionType(mappedKeys);
23477+ if (forSource && apparentKeys.flags & TypeFlags.Never) {
23478+ // modifiers type of mapped type is often `unknown`, `keyof unknown` is `never` and that's assignable to everything
23479+ // letting this through is too permissive so we use the apparent type of an index type here instead
23480+ return stringNumberSymbolType;
23481+ }
23482+ return apparentKeys;
2347723483 }
2347823484
2347923485 function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType<typeof captureErrorCalculationState>): Ternary {
@@ -23657,7 +23663,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2365723663 if (nameType && isMappedTypeWithKeyofConstraintDeclaration(targetType)) {
2365823664 // we need to get the apparent mappings and union them with the generic mappings, since some properties may be
2365923665 // missing from the `constraintType` which will otherwise be mapped in the object
23660- const mappedKeys = getApparentMappedTypeKeys(nameType, targetType);
23666+ const mappedKeys = getApparentMappedTypeKeys(nameType, targetType, /*forSource*/ false );
2366123667 // We still need to include the non-apparent (and thus still generic) keys in the target side of the comparison (in case they're in the source side)
2366223668 targetKeys = getUnionType([mappedKeys, nameType]);
2366323669 }
@@ -23864,18 +23870,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2386423870 // allow assignments of index types of identical (or similar enough) mapped types.
2386523871 // eg, `keyof {[X in keyof A]: Obj[X]}` should be assignable to `keyof {[Y in keyof A]: Tup[Y]}` because both map over the same set of keys (`keyof A`).
2386623872 // Without this source-side breakdown, a `keyof {[X in keyof A]: Obj[X]}` style type won't be assignable to anything except itself, which is much too strict.
23867- let sourceMappedKeys: Type;
23868- if (nameType && isMappedTypeWithKeyofConstraintDeclaration(mappedType)) {
23869- sourceMappedKeys = getApparentMappedTypeKeys(nameType, mappedType);
23870- if (sourceMappedKeys.flags & TypeFlags.Never) {
23871- // modifiers type of mapped type is often `unknown`, `keyof unknown` is `never` and that's assignable to everything
23872- // letting this through is too permissive so we use the apparent type of an index type here instead
23873- sourceMappedKeys = stringNumberSymbolType;
23874- }
23875- }
23876- else {
23877- sourceMappedKeys = nameType || getConstraintTypeFromMappedType(mappedType);
23878- }
23873+ const sourceMappedKeys = nameType && isMappedTypeWithKeyofConstraintDeclaration(mappedType) ? getApparentMappedTypeKeys(nameType, mappedType, /*forSource*/ true) : (nameType || getConstraintTypeFromMappedType(mappedType));
2387923874 if (result = isRelatedTo(sourceMappedKeys, target, RecursionFlags.Source, reportErrors)) {
2388023875 return result;
2388123876 }
0 commit comments