Skip to content

Commit e14412a

Browse files
committed
Improve handling of modifiers in mapped type inference
1 parent 4c9bdb9 commit e14412a

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4532,7 +4532,7 @@ namespace ts {
45324532
const isomorphicProp = isomorphicType && getPropertyOfType(isomorphicType, propName);
45334533
const isOptional = templateOptional || !!(isomorphicProp && isomorphicProp.flags & SymbolFlags.Optional);
45344534
const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | (isOptional ? SymbolFlags.Optional : 0), propName);
4535-
prop.type = addOptionality(propType, isOptional);
4535+
prop.type = propType;
45364536
prop.isReadonly = templateReadonly || isomorphicProp && isReadonlySymbol(isomorphicProp);
45374537
members[propName] = prop;
45384538
}
@@ -4556,7 +4556,7 @@ namespace ts {
45564556
function getTemplateTypeFromMappedType(type: MappedType) {
45574557
return type.templateType ||
45584558
(type.templateType = type.declaration.type ?
4559-
instantiateType(getTypeFromTypeNode(type.declaration.type), type.mapper || identityMapper) :
4559+
instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), !!type.declaration.questionToken), type.mapper || identityMapper) :
45604560
unknownType);
45614561
}
45624562

@@ -6021,7 +6021,7 @@ namespace ts {
60216021
}
60226022
const mapper = createUnaryTypeMapper(getTypeParameterFromMappedType(type), indexType);
60236023
const templateMapper = type.mapper ? combineTypeMappers(type.mapper, mapper) : mapper;
6024-
return addOptionality(instantiateType(getTemplateTypeFromMappedType(type), templateMapper), !!type.declaration.questionToken);
6024+
return instantiateType(getTemplateTypeFromMappedType(type), templateMapper);
60256025
}
60266026

60276027
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
@@ -8484,16 +8484,18 @@ namespace ts {
84848484
const typeInferences = createTypeInferencesObject();
84858485
const typeInferencesArray = [typeInferences];
84868486
const templateType = getTemplateTypeFromMappedType(target);
8487+
const readonlyMask = target.declaration.readonlyToken ? false : true;
8488+
const optionalMask = target.declaration.questionToken ? 0 : SymbolFlags.Optional;
84878489
const properties = getPropertiesOfType(source);
84888490
const members = createSymbolTable(properties);
84898491
let hasInferredTypes = false;
84908492
for (const prop of properties) {
84918493
const inferredPropType = inferTargetType(getTypeOfSymbol(prop));
84928494
if (inferredPropType) {
8493-
const inferredProp = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | prop.flags & SymbolFlags.Optional, prop.name);
8495+
const inferredProp = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | prop.flags & optionalMask, prop.name);
84948496
inferredProp.declarations = prop.declarations;
84958497
inferredProp.type = inferredPropType;
8496-
inferredProp.isReadonly = isReadonlySymbol(prop);
8498+
inferredProp.isReadonly = readonlyMask && isReadonlySymbol(prop);
84978499
members[prop.name] = inferredProp;
84988500
hasInferredTypes = true;
84998501
}
@@ -8502,7 +8504,7 @@ namespace ts {
85028504
if (indexInfo) {
85038505
const inferredIndexType = inferTargetType(indexInfo.type);
85048506
if (inferredIndexType) {
8505-
indexInfo = createIndexInfo(inferredIndexType, indexInfo.isReadonly);
8507+
indexInfo = createIndexInfo(inferredIndexType, readonlyMask && indexInfo.isReadonly);
85068508
hasInferredTypes = true;
85078509
}
85088510
}

0 commit comments

Comments
 (0)