Skip to content

Commit dab0d38

Browse files
committed
Fixed symbol declarations for generic filtering mapped types
1 parent f2df10f commit dab0d38

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

src/compiler/checker.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13174,8 +13174,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1317413174
// and T as the template type.
1317513175
const typeParameter = getTypeParameterFromMappedType(type);
1317613176
const constraintType = getConstraintTypeFromMappedType(type);
13177-
const nameType = getNameTypeFromMappedType(type.target as MappedType || type);
13178-
const isFilteringMappedType = nameType && isTypeAssignableTo(nameType, typeParameter);
13177+
const mappedType = (type.target as MappedType) || type;
13178+
const nameType = getNameTypeFromMappedType(mappedType);
13179+
const shouldLinkPropDeclarations = !nameType || isFilteringMappedType(mappedType);
1317913180
const templateType = getTemplateTypeFromMappedType(type.target as MappedType || type);
1318013181
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
1318113182
const templateModifiers = getMappedTypeModifiers(type);
@@ -13222,7 +13223,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1322213223
prop.links.keyType = keyType;
1322313224
if (modifiersProp) {
1322413225
prop.links.syntheticOrigin = modifiersProp;
13225-
prop.declarations = !nameType || isFilteringMappedType ? modifiersProp.declarations : undefined;
13226+
prop.declarations = shouldLinkPropDeclarations ? modifiersProp.declarations : undefined;
1322613227
}
1322713228
members.set(propName, prop);
1322813229
}
@@ -13355,6 +13356,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1335513356
return false;
1335613357
}
1335713358

13359+
function isFilteringMappedType(type: MappedType): boolean {
13360+
const nameType = getNameTypeFromMappedType(type);
13361+
return !!nameType && isTypeAssignableTo(nameType, getTypeParameterFromMappedType(type));
13362+
}
13363+
1335813364
function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
1335913365
if (!(type as ResolvedType).members) {
1336013366
if (type.flags & TypeFlags.Object) {
@@ -17473,8 +17479,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1747317479
// K is generic and N is assignable to P, instantiate E using a mapper that substitutes the index type for P.
1747417480
// For example, for an index access { [P in K]: Box<T[P]> }[X], we construct the type Box<T[X]>.
1747517481
if (isGenericMappedType(objectType)) {
17476-
const nameType = getNameTypeFromMappedType(objectType);
17477-
if (!nameType || isTypeAssignableTo(nameType, getTypeParameterFromMappedType(objectType))) {
17482+
if (!getNameTypeFromMappedType(objectType) || isFilteringMappedType(objectType)) {
1747817483
return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t, writing));
1747917484
}
1748017485
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
///<reference path="fourslash.ts"/>
2+
3+
//// const obj = {
4+
//// get /*def*/id() {
5+
//// return 1;
6+
//// },
7+
//// name: "test",
8+
//// };
9+
////
10+
//// type Omit2<T, DroppedKeys extends PropertyKey> = {
11+
//// [K in keyof T as Exclude<K, DroppedKeys>]: T[K];
12+
//// };
13+
////
14+
//// declare function omit2<O, Mask extends { [K in keyof O]?: true }>(
15+
//// obj: O,
16+
//// mask: Mask
17+
//// ): Omit2<O, keyof Mask>;
18+
////
19+
//// const obj2 = omit2(obj, {
20+
//// name: true,
21+
//// });
22+
////
23+
//// obj2.[|/*ref*/id|];
24+
25+
verify.goToDefinition("ref", "def");

0 commit comments

Comments
 (0)