Skip to content

Support find-all-references on mapped types. #13658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
2 commits merged into from
Jan 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4618,12 +4618,14 @@ namespace ts {
const typeParameter = getTypeParameterFromMappedType(type);
const constraintType = getConstraintTypeFromMappedType(type);
const templateType = getTemplateTypeFromMappedType(type);
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type));
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
const templateReadonly = !!type.declaration.readonlyToken;
const templateOptional = !!type.declaration.questionToken;
if (type.declaration.typeParameter.constraint.kind === SyntaxKind.TypeOperator) {
// We have a { [P in keyof T]: X }
forEachType(getLiteralTypeFromPropertyNames(modifiersType), addMemberForKeyType);
for (const propertySymbol of getPropertiesOfType(modifiersType)) {
addMemberForKeyType(getLiteralTypeFromPropertyName(propertySymbol), propertySymbol);
}
if (getIndexInfoOfType(modifiersType, IndexKind.String)) {
addMemberForKeyType(stringType);
}
Expand All @@ -4638,7 +4640,7 @@ namespace ts {
}
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);

function addMemberForKeyType(t: Type) {
function addMemberForKeyType(t: Type, propertySymbol?: Symbol) {
// Create a mapper from T to the current iteration type constituent. Then, if the
// mapped type is itself an instantiated type, combine the iteration mapper with the
// instantiation mapper.
Expand All @@ -4654,6 +4656,9 @@ namespace ts {
const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | (isOptional ? SymbolFlags.Optional : 0), propName);
prop.type = propType;
prop.isReadonly = templateReadonly || modifiersProp && isReadonlySymbol(modifiersProp);
if (propertySymbol) {
prop.mappedTypeOrigin = propertySymbol;
}
members.set(propName, prop);
}
else if (t.flags & TypeFlags.String) {
Expand Down Expand Up @@ -20230,6 +20235,10 @@ namespace ts {
const links = symbol as SymbolLinks;
return [links.leftSpread, links.rightSpread];
}
if ((symbol as SymbolLinks).mappedTypeOrigin) {
return getRootSymbols((symbol as SymbolLinks).mappedTypeOrigin);
}

let target: Symbol;
let next = symbol;
while (next = getSymbolLinks(next).target) {
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2712,6 +2712,7 @@
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
leftSpread?: Symbol; // Left source for synthetic spread property
rightSpread?: Symbol; // Right source for synthetic spread property
mappedTypeOrigin?: Symbol; // For a property on a mapped type, points back to the orignal 'T' from 'keyof T'.
hasNonUniformType?: boolean; // True if constituents have non-uniform types
isPartial?: boolean; // True if syntheric property of union type occurs in some but not all constituents
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/mappedTypes1.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ declare let x2: string;
declare let x3: number;
declare let x4: {
toString: void;
valueOf: void;
toFixed: void;
toExponential: void;
toPrecision: void;
valueOf: void;
toLocaleString: void;
};
4 changes: 2 additions & 2 deletions tests/baselines/reference/mappedTypes1.types
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ let x3 = f3();
>f3 : <T1 extends number>() => { [P in keyof T1]: void; }

let x4 = f4();
>x4 : { toString: void; valueOf: void; toFixed: void; toExponential: void; toPrecision: void; toLocaleString: void; }
>f4() : { toString: void; valueOf: void; toFixed: void; toExponential: void; toPrecision: void; toLocaleString: void; }
>x4 : { toString: void; toFixed: void; toExponential: void; toPrecision: void; valueOf: void; toLocaleString: void; }
>f4() : { toString: void; toFixed: void; toExponential: void; toPrecision: void; valueOf: void; toLocaleString: void; }
>f4 : <T1 extends Number>() => { [P in keyof T1]: void; }

9 changes: 9 additions & 0 deletions tests/cases/fourslash/findAllRefsForMappedType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/// <reference path='fourslash.ts'/>

////interface T { [|a|]: number };
////type U { [K in keyof T]: string };
////type V = { [K in keyof U]: boolean };
////const u: U = { [|a|]: "" }
////const v: V = { [|a|]: true }

verify.rangesReferenceEachOther();