Skip to content

Commit 0d21c24

Browse files
author
Andy Hanson
committed
Support find-all-references on mapped types.
* Need to put a 'mappedTypeOrigin' property in SymbolLinks
1 parent 4888e4f commit 0d21c24

File tree

3 files changed

+22
-3
lines changed

3 files changed

+22
-3
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4618,12 +4618,14 @@ namespace ts {
46184618
const typeParameter = getTypeParameterFromMappedType(type);
46194619
const constraintType = getConstraintTypeFromMappedType(type);
46204620
const templateType = getTemplateTypeFromMappedType(type);
4621-
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type));
4621+
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
46224622
const templateReadonly = !!type.declaration.readonlyToken;
46234623
const templateOptional = !!type.declaration.questionToken;
46244624
if (type.declaration.typeParameter.constraint.kind === SyntaxKind.TypeOperator) {
46254625
// We have a { [P in keyof T]: X }
4626-
forEachType(getLiteralTypeFromPropertyNames(modifiersType), addMemberForKeyType);
4626+
for (const propertySymbol of getPropertiesOfType(modifiersType)) {
4627+
addMemberForKeyType(getLiteralTypeFromPropertyName(propertySymbol), propertySymbol);
4628+
}
46274629
if (getIndexInfoOfType(modifiersType, IndexKind.String)) {
46284630
addMemberForKeyType(stringType);
46294631
}
@@ -4638,7 +4640,7 @@ namespace ts {
46384640
}
46394641
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
46404642

4641-
function addMemberForKeyType(t: Type) {
4643+
function addMemberForKeyType(t: Type, propertySymbol?: Symbol) {
46424644
// Create a mapper from T to the current iteration type constituent. Then, if the
46434645
// mapped type is itself an instantiated type, combine the iteration mapper with the
46444646
// instantiation mapper.
@@ -4654,6 +4656,9 @@ namespace ts {
46544656
const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | (isOptional ? SymbolFlags.Optional : 0), propName);
46554657
prop.type = propType;
46564658
prop.isReadonly = templateReadonly || modifiersProp && isReadonlySymbol(modifiersProp);
4659+
if (propertySymbol) {
4660+
prop.mappedTypeOrigin = propertySymbol;
4661+
}
46574662
members.set(propName, prop);
46584663
}
46594664
else if (t.flags & TypeFlags.String) {
@@ -20230,6 +20235,10 @@ namespace ts {
2023020235
const links = symbol as SymbolLinks;
2023120236
return [links.leftSpread, links.rightSpread];
2023220237
}
20238+
if ((symbol as SymbolLinks).mappedTypeOrigin) {
20239+
return getRootSymbols((symbol as SymbolLinks).mappedTypeOrigin);
20240+
}
20241+
2023320242
let target: Symbol;
2023420243
let next = symbol;
2023520244
while (next = getSymbolLinks(next).target) {

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2712,6 +2712,7 @@
27122712
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
27132713
leftSpread?: Symbol; // Left source for synthetic spread property
27142714
rightSpread?: Symbol; // Right source for synthetic spread property
2715+
mappedTypeOrigin?: Symbol; // For a property on a mapped type, points back to the orignal 'T' from 'keyof T'.
27152716
hasNonUniformType?: boolean; // True if constituents have non-uniform types
27162717
isPartial?: boolean; // True if syntheric property of union type occurs in some but not all constituents
27172718
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
////interface T { [|a|]: number };
4+
////type U { [K in keyof T]: string };
5+
////type V = { [K in keyof U]: boolean };
6+
////const u: U = { [|a|]: "" }
7+
////const v: V = { [|a|]: true }
8+
9+
verify.rangesReferenceEachOther();

0 commit comments

Comments
 (0)