From 546f5d7f2e63adb1a00c9fcb6287a44022345ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 24 Oct 2023 09:12:55 +0200 Subject: [PATCH] Fixed types of properties of contextual filtering mapped types --- src/compiler/checker.ts | 2 +- ...opertyOfGenericFilteringMappedType.symbols | 90 +++++++++++++++++++ ...PropertyOfGenericFilteringMappedType.types | 89 ++++++++++++++++++ ...ualPropertyOfGenericFilteringMappedType.ts | 33 +++++++ 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.symbols create mode 100644 tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.types create mode 100644 tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4cd242f264b1a..0e73136b365d6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29976,7 +29976,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { return mapType(type, t => { - if (isGenericMappedType(t) && !t.declaration.nameType) { + if (isGenericMappedType(t) && (!t.declaration.nameType || isFilteringMappedType(t))) { const constraint = getConstraintTypeFromMappedType(t); const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); diff --git a/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.symbols b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.symbols new file mode 100644 index 0000000000000..5bcaba07ec255 --- /dev/null +++ b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.symbols @@ -0,0 +1,90 @@ +//// [tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts] //// + +=== contextualPropertyOfGenericFilteringMappedType.ts === +declare function f1( +>f1 : Symbol(f1, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 0, 0)) +>T : Symbol(T, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 0, 20)) + + data: T, +>data : Symbol(data, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 0, 38)) +>T : Symbol(T, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 0, 20)) + + handlers: { [P in keyof T as P]: (value: T[P], prop: P) => void }, +>handlers : Symbol(handlers, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 1, 10)) +>P : Symbol(P, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 2, 15)) +>T : Symbol(T, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 0, 20)) +>P : Symbol(P, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 2, 15)) +>value : Symbol(value, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 2, 36)) +>T : Symbol(T, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 0, 20)) +>P : Symbol(P, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 2, 15)) +>prop : Symbol(prop, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 2, 48)) +>P : Symbol(P, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 2, 15)) + +): void; + +f1( +>f1 : Symbol(f1, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 0, 0)) + { + foo: 0, +>foo : Symbol(foo, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 6, 3)) + + bar: "", +>bar : Symbol(bar, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 7, 11)) + + }, + { + foo: (value, key) => {}, +>foo : Symbol(foo, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 10, 3)) +>value : Symbol(value, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 11, 10)) +>key : Symbol(key, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 11, 16)) + + bar: (value, key) => {}, +>bar : Symbol(bar, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 11, 28)) +>value : Symbol(value, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 12, 10)) +>key : Symbol(key, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 12, 16)) + + }, +); + +declare function f2( +>f2 : Symbol(f2, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 14, 2)) +>T : Symbol(T, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 16, 20)) + + data: T, +>data : Symbol(data, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 16, 38)) +>T : Symbol(T, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 16, 20)) + + handlers: { [P in keyof T as T[P] extends string ? P : never]: (value: T[P], prop: P) => void }, +>handlers : Symbol(handlers, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 17, 10)) +>P : Symbol(P, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 18, 15)) +>T : Symbol(T, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 16, 20)) +>T : Symbol(T, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 16, 20)) +>P : Symbol(P, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 18, 15)) +>P : Symbol(P, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 18, 15)) +>value : Symbol(value, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 18, 66)) +>T : Symbol(T, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 16, 20)) +>P : Symbol(P, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 18, 15)) +>prop : Symbol(prop, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 18, 78)) +>P : Symbol(P, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 18, 15)) + +): void; + +f2( +>f2 : Symbol(f2, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 14, 2)) + { + foo: 0, +>foo : Symbol(foo, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 22, 3)) + + bar: "", +>bar : Symbol(bar, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 23, 11)) + + }, + { + bar: (value, key) => {}, +>bar : Symbol(bar, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 26, 3)) +>value : Symbol(value, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 27, 10)) +>key : Symbol(key, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 27, 16)) + + }, +); + diff --git a/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.types b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.types new file mode 100644 index 0000000000000..bd334de35d6f7 --- /dev/null +++ b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.types @@ -0,0 +1,89 @@ +//// [tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts] //// + +=== contextualPropertyOfGenericFilteringMappedType.ts === +declare function f1( +>f1 : (data: T, handlers: { [P in keyof T as P]: (value: T[P], prop: P) => void; }) => void + + data: T, +>data : T + + handlers: { [P in keyof T as P]: (value: T[P], prop: P) => void }, +>handlers : { [P in keyof T as P]: (value: T[P], prop: P) => void; } +>value : T[P] +>prop : P + +): void; + +f1( +>f1( { foo: 0, bar: "", }, { foo: (value, key) => {}, bar: (value, key) => {}, },) : void +>f1 : (data: T, handlers: { [P in keyof T as P]: (value: T[P], prop: P) => void; }) => void + { +>{ foo: 0, bar: "", } : { foo: number; bar: string; } + + foo: 0, +>foo : number +>0 : 0 + + bar: "", +>bar : string +>"" : "" + + }, + { +>{ foo: (value, key) => {}, bar: (value, key) => {}, } : { foo: (value: number, key: "foo") => void; bar: (value: string, key: "bar") => void; } + + foo: (value, key) => {}, +>foo : (value: number, key: "foo") => void +>(value, key) => {} : (value: number, key: "foo") => void +>value : number +>key : "foo" + + bar: (value, key) => {}, +>bar : (value: string, key: "bar") => void +>(value, key) => {} : (value: string, key: "bar") => void +>value : string +>key : "bar" + + }, +); + +declare function f2( +>f2 : (data: T, handlers: { [P in keyof T as T[P] extends string ? P : never]: (value: T[P], prop: P) => void; }) => void + + data: T, +>data : T + + handlers: { [P in keyof T as T[P] extends string ? P : never]: (value: T[P], prop: P) => void }, +>handlers : { [P in keyof T as T[P] extends string ? P : never]: (value: T[P], prop: P) => void; } +>value : T[P] +>prop : P + +): void; + +f2( +>f2( { foo: 0, bar: "", }, { bar: (value, key) => {}, },) : void +>f2 : (data: T, handlers: { [P in keyof T as T[P] extends string ? P : never]: (value: T[P], prop: P) => void; }) => void + { +>{ foo: 0, bar: "", } : { foo: number; bar: string; } + + foo: 0, +>foo : number +>0 : 0 + + bar: "", +>bar : string +>"" : "" + + }, + { +>{ bar: (value, key) => {}, } : { bar: (value: string, key: "bar") => void; } + + bar: (value, key) => {}, +>bar : (value: string, key: "bar") => void +>(value, key) => {} : (value: string, key: "bar") => void +>value : string +>key : "bar" + + }, +); + diff --git a/tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts b/tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts new file mode 100644 index 0000000000000..824a6d554344c --- /dev/null +++ b/tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts @@ -0,0 +1,33 @@ +// @strict: true +// @noEmit: true + +declare function f1( + data: T, + handlers: { [P in keyof T as P]: (value: T[P], prop: P) => void }, +): void; + +f1( + { + foo: 0, + bar: "", + }, + { + foo: (value, key) => {}, + bar: (value, key) => {}, + }, +); + +declare function f2( + data: T, + handlers: { [P in keyof T as T[P] extends string ? P : never]: (value: T[P], prop: P) => void }, +): void; + +f2( + { + foo: 0, + bar: "", + }, + { + bar: (value, key) => {}, + }, +);