Repository navigation
Unexpected intersection inferred from indexed type #35695
Description
Activity
dragomirtitian commented
on Dec 16, 2019 ContributorMore actionsNot really unexpected. Inside the function
Kcan be anykeyof DataTypes. This means thatdata[key]could be((value: string) => void) | ((value: number) => void). Such a union is invokable only with an intersection of all possible parameter types (see PR). So this means the parameter would need to bestring & number. Intersections of incompatible primitive types reduce toneverso you end up withdata[key]being effectively(value: never) => void.To get this to work you would need some kind of correlated types such as Joe Calzaretta (@jcalz) proposes here.
Titian Cernicova-Dragomir (@dragomirtitian) Thanks for your detailed explanation.
I know the inner logic now but my question is can the inferred type of
data[key]be just more specific (fromData[K]to the definition ofData[K]), which may be easier to implement? I think it's different from #31445 and #30581.Or, in other words, can we get actual typings for type parameters from indexed types (or inferences, however an index signature parameter type cannot be a union type)?
dragomirtitian commented
on Dec 16, 2019 ContributorMore actionsShigma (@shigma) I don't think there is any way to get the implementation types to work out except for a type assertion or using a separate implementation signature:
function myFunc<K extends keyof DataTypes>(data: Data, key: K, value: DataTypes[K]): void { (data[key] as (value: DataTypes[K]) => void)(value); }
- addedWorking as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
on Dec 20, 2019 RyanCavanaugh commented
on Dec 20, 2019 MemberMore actionsThis is a correct error; a legal call to
myFuncisdeclare const data: Data; declare const ab: "a" | "b"; myFunc(data, ab, "");
which corrupts
datawhenabis"b"There isn't a sound way to write the function signature, thus no way to correctly implement the body. You can use a type assertion if you pinky-swear to only call it with unit keys.
Thanks. I will close this issue.
- locked as resolved and limited conversation to collaborators
on Oct 21, 2025
TypeScript Version: 3.7.2
Search Terms: type alias index signature intersection TS2345
Expected behavior: pass the type checks
Actual behavior: fail with a TS2345 error
Related Issues: #31445, #35613
Note: Although #35613 is marked as duplicated, I think a different approach than #31445 can be used to address this issue. Actually
data[key]can be inferred as(value: DataTypes[K]) => void, which solves the problem.Code
Output
Compiler Options
{ "compilerOptions": { "noImplicitAny": true, "strictNullChecks": true, "strictFunctionTypes": true, "strictPropertyInitialization": true, "strictBindCallApply": true, "noImplicitThis": true, "noImplicitReturns": true, "useDefineForClassFields": false, "alwaysStrict": true, "allowUnreachableCode": false, "allowUnusedLabels": false, "downlevelIteration": false, "noEmitHelpers": false, "noLib": false, "noStrictGenericChecks": false, "noUnusedLocals": false, "noUnusedParameters": false, "esModuleInterop": true, "preserveConstEnums": false, "removeComments": false, "skipLibCheck": false, "checkJs": false, "allowJs": false, "declaration": true, "experimentalDecorators": false, "emitDecoratorMetadata": false, "target": "ES2017", "module": "ESNext" } }Playground Link: Provided