diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index da31a1c39c6..e4c2bf2250f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19709,7 +19709,8 @@ namespace ts { // arrow function, but is considered partially inferable because property 'a' has an inferable type. function isPartiallyInferableType(type: Type): boolean { return !(getObjectFlags(type) & ObjectFlags.NonInferrableType) || - isObjectLiteralType(type) && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop))); + isObjectLiteralType(type) && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop))) || + isTupleType(type) && some(getTypeArguments(type), isPartiallyInferableType); } function createReverseMappedType(source: Type, target: MappedType, constraint: IndexType) { diff --git a/tests/baselines/reference/reverseMappedPartiallyInferableTypes.errors.txt b/tests/baselines/reference/reverseMappedPartiallyInferableTypes.errors.txt index 63ea9a9f279..bd3697aaaff 100644 --- a/tests/baselines/reference/reverseMappedPartiallyInferableTypes.errors.txt +++ b/tests/baselines/reference/reverseMappedPartiallyInferableTypes.errors.txt @@ -98,4 +98,36 @@ tests/cases/compiler/reverseMappedPartiallyInferableTypes.ts(91,20): error TS257 } } }); + + // Repros from #40809 + + type Mapped1 = { + [K in keyof T]: [T[K], (arg: T) => boolean]; + }; + + declare function inferMapped1(arg: Mapped1): void; + + inferMapped1({ + key: [3, arg => arg.key > 5] + }); + + type Mapped2 = { + [K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean]; + }; + + declare function inferMapped2(arg: Mapped2): void; + + inferMapped2({ + key: [3, arg => arg.key > 5] + }); + + type MappedReadonly = { + readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean]; + }; + + declare function inferMappedReadonly(arg: MappedReadonly): void; + + inferMappedReadonly({ + key: [3, arg => arg.key > 5] + }); \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedPartiallyInferableTypes.js b/tests/baselines/reference/reverseMappedPartiallyInferableTypes.js index e5a9c2a57ae..fbd70a5bb65 100644 --- a/tests/baselines/reference/reverseMappedPartiallyInferableTypes.js +++ b/tests/baselines/reference/reverseMappedPartiallyInferableTypes.js @@ -93,6 +93,38 @@ const obj3 = id({ } } }); + +// Repros from #40809 + +type Mapped1 = { + [K in keyof T]: [T[K], (arg: T) => boolean]; +}; + +declare function inferMapped1(arg: Mapped1): void; + +inferMapped1({ + key: [3, arg => arg.key > 5] +}); + +type Mapped2 = { + [K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean]; +}; + +declare function inferMapped2(arg: Mapped2): void; + +inferMapped2({ + key: [3, arg => arg.key > 5] +}); + +type MappedReadonly = { + readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean]; +}; + +declare function inferMappedReadonly(arg: MappedReadonly): void; + +inferMappedReadonly({ + key: [3, arg => arg.key > 5] +}); //// [reverseMappedPartiallyInferableTypes.js] @@ -142,3 +174,12 @@ var obj3 = id({ } } }); +inferMapped1({ + key: [3, function (arg) { return arg.key > 5; }] +}); +inferMapped2({ + key: [3, function (arg) { return arg.key > 5; }] +}); +inferMappedReadonly({ + key: [3, function (arg) { return arg.key > 5; }] +}); diff --git a/tests/baselines/reference/reverseMappedPartiallyInferableTypes.symbols b/tests/baselines/reference/reverseMappedPartiallyInferableTypes.symbols index ac264a37e9e..6ababcbb9f1 100644 --- a/tests/baselines/reference/reverseMappedPartiallyInferableTypes.symbols +++ b/tests/baselines/reference/reverseMappedPartiallyInferableTypes.symbols @@ -257,3 +257,105 @@ const obj3 = id({ } }); +// Repros from #40809 + +type Mapped1 = { +>Mapped1 : Symbol(Mapped1, Decl(reverseMappedPartiallyInferableTypes.ts, 93, 3)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 97, 13)) + + [K in keyof T]: [T[K], (arg: T) => boolean]; +>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 98, 5)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 97, 13)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 97, 13)) +>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 98, 5)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 98, 28)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 97, 13)) + +}; + +declare function inferMapped1(arg: Mapped1): void; +>inferMapped1 : Symbol(inferMapped1, Decl(reverseMappedPartiallyInferableTypes.ts, 99, 2)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 101, 30)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 101, 33)) +>Mapped1 : Symbol(Mapped1, Decl(reverseMappedPartiallyInferableTypes.ts, 93, 3)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 101, 30)) + +inferMapped1({ +>inferMapped1 : Symbol(inferMapped1, Decl(reverseMappedPartiallyInferableTypes.ts, 99, 2)) + + key: [3, arg => arg.key > 5] +>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 103, 14)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 104, 12)) +>arg.key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 103, 14)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 104, 12)) +>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 103, 14)) + +}); + +type Mapped2 = { +>Mapped2 : Symbol(Mapped2, Decl(reverseMappedPartiallyInferableTypes.ts, 105, 3)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13)) + + [K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean]; +>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 108, 5)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13)) +>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 108, 5)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 108, 58)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13)) + +}; + +declare function inferMapped2(arg: Mapped2): void; +>inferMapped2 : Symbol(inferMapped2, Decl(reverseMappedPartiallyInferableTypes.ts, 109, 2)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 111, 30)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 111, 33)) +>Mapped2 : Symbol(Mapped2, Decl(reverseMappedPartiallyInferableTypes.ts, 105, 3)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 111, 30)) + +inferMapped2({ +>inferMapped2 : Symbol(inferMapped2, Decl(reverseMappedPartiallyInferableTypes.ts, 109, 2)) + + key: [3, arg => arg.key > 5] +>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 113, 14)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 114, 12)) +>arg.key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 113, 14)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 114, 12)) +>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 113, 14)) + +}); + +type MappedReadonly = { +>MappedReadonly : Symbol(MappedReadonly, Decl(reverseMappedPartiallyInferableTypes.ts, 115, 3)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 117, 20)) + + readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean]; +>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 118, 14)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 117, 20)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 117, 20)) +>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 118, 14)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 118, 46)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 117, 20)) + +}; + +declare function inferMappedReadonly(arg: MappedReadonly): void; +>inferMappedReadonly : Symbol(inferMappedReadonly, Decl(reverseMappedPartiallyInferableTypes.ts, 119, 2)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 121, 37)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 121, 40)) +>MappedReadonly : Symbol(MappedReadonly, Decl(reverseMappedPartiallyInferableTypes.ts, 115, 3)) +>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 121, 37)) + +inferMappedReadonly({ +>inferMappedReadonly : Symbol(inferMappedReadonly, Decl(reverseMappedPartiallyInferableTypes.ts, 119, 2)) + + key: [3, arg => arg.key > 5] +>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 123, 21)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 124, 12)) +>arg.key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 123, 21)) +>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 124, 12)) +>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 123, 21)) + +}); + diff --git a/tests/baselines/reference/reverseMappedPartiallyInferableTypes.types b/tests/baselines/reference/reverseMappedPartiallyInferableTypes.types index e2b8ba8b5fa..8a06b7c6d5e 100644 --- a/tests/baselines/reference/reverseMappedPartiallyInferableTypes.types +++ b/tests/baselines/reference/reverseMappedPartiallyInferableTypes.types @@ -229,3 +229,98 @@ const obj3 = id({ } }); +// Repros from #40809 + +type Mapped1 = { +>Mapped1 : Mapped1 + + [K in keyof T]: [T[K], (arg: T) => boolean]; +>arg : T + +}; + +declare function inferMapped1(arg: Mapped1): void; +>inferMapped1 : (arg: Mapped1) => void +>arg : Mapped1 + +inferMapped1({ +>inferMapped1({ key: [3, arg => arg.key > 5]}) : void +>inferMapped1 : (arg: Mapped1) => void +>{ key: [3, arg => arg.key > 5]} : { key: [number, (arg: { key: number; }) => boolean]; } + + key: [3, arg => arg.key > 5] +>key : [number, (arg: { key: number; }) => boolean] +>[3, arg => arg.key > 5] : [number, (arg: { key: number; }) => boolean] +>3 : 3 +>arg => arg.key > 5 : (arg: { key: number; }) => boolean +>arg : { key: number; } +>arg.key > 5 : boolean +>arg.key : number +>arg : { key: number; } +>key : number +>5 : 5 + +}); + +type Mapped2 = { +>Mapped2 : Mapped2 + + [K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean]; +>arg : T + +}; + +declare function inferMapped2(arg: Mapped2): void; +>inferMapped2 : (arg: Mapped2) => void +>arg : Mapped2 + +inferMapped2({ +>inferMapped2({ key: [3, arg => arg.key > 5]}) : void +>inferMapped2 : (arg: Mapped2) => void +>{ key: [3, arg => arg.key > 5]} : { key: [number, (arg: { key: number; }) => boolean]; } + + key: [3, arg => arg.key > 5] +>key : [number, (arg: { key: number; }) => boolean] +>[3, arg => arg.key > 5] : [number, (arg: { key: number; }) => boolean] +>3 : 3 +>arg => arg.key > 5 : (arg: { key: number; }) => boolean +>arg : { key: number; } +>arg.key > 5 : boolean +>arg.key : number +>arg : { key: number; } +>key : number +>5 : 5 + +}); + +type MappedReadonly = { +>MappedReadonly : MappedReadonly + + readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean]; +>arg : T + +}; + +declare function inferMappedReadonly(arg: MappedReadonly): void; +>inferMappedReadonly : (arg: MappedReadonly) => void +>arg : MappedReadonly + +inferMappedReadonly({ +>inferMappedReadonly({ key: [3, arg => arg.key > 5]}) : void +>inferMappedReadonly : (arg: MappedReadonly) => void +>{ key: [3, arg => arg.key > 5]} : { key: [number, (arg: { key: number; }) => boolean]; } + + key: [3, arg => arg.key > 5] +>key : [number, (arg: { key: number; }) => boolean] +>[3, arg => arg.key > 5] : [number, (arg: { key: number; }) => boolean] +>3 : 3 +>arg => arg.key > 5 : (arg: { key: number; }) => boolean +>arg : { key: number; } +>arg.key > 5 : boolean +>arg.key : number +>arg : { key: number; } +>key : number +>5 : 5 + +}); + diff --git a/tests/cases/compiler/reverseMappedPartiallyInferableTypes.ts b/tests/cases/compiler/reverseMappedPartiallyInferableTypes.ts index 799ff641c5a..5f93bfb3ac6 100644 --- a/tests/cases/compiler/reverseMappedPartiallyInferableTypes.ts +++ b/tests/cases/compiler/reverseMappedPartiallyInferableTypes.ts @@ -94,3 +94,35 @@ const obj3 = id({ } } }); + +// Repros from #40809 + +type Mapped1 = { + [K in keyof T]: [T[K], (arg: T) => boolean]; +}; + +declare function inferMapped1(arg: Mapped1): void; + +inferMapped1({ + key: [3, arg => arg.key > 5] +}); + +type Mapped2 = { + [K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean]; +}; + +declare function inferMapped2(arg: Mapped2): void; + +inferMapped2({ + key: [3, arg => arg.key > 5] +}); + +type MappedReadonly = { + readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean]; +}; + +declare function inferMappedReadonly(arg: MappedReadonly): void; + +inferMappedReadonly({ + key: [3, arg => arg.key > 5] +});