The following code fails as TypeScript:
const exampleFn = function<AttributeName extends 'attributeA' | 'attributeB'>(
whatToProcess: AttributeName extends 'attributeA' ? {attributeA: string} : {attributeB: string},
attributeName: AttributeName
) {
//Error here: Type 'AttributeName' cannot be used to index type
//'AttributeName extends "attributeA" ? { attributeA: string; } : { attributeB: string; }'.ts(2536)
console.log(whatToProcess[attributeName]);
}
Playground link here.
When attributeName is 'attributeA', whatToProcess should have attributeA, and when attributeName is 'attributeB', whatToProcess should have attributeB, so in each case attributeName should be usable to index the type of whatToProcess.
It seems I'm not understanding something about how the generic + conditional typing system works in TypeScript; if someone can help me figure out how this is supposed to be done that'd be much appreciated!
TypeScript cannot link
AttributeName
as a key of{attributeA: string}
or{attributeB: string}
because the resultantwhatToProcess
argument is an object that cannot be accessed by arbitrary strings. Additionally, TypeScript will not know what the object is going to be in runtime, hence you will be forced to build code to cater for all cases either way.I believe there is a better way to solve your problem. What you are trying to constrain here is the ability for the developer to access the object using specific keys. This object could be either
{attributeA: string}
or{attributeB: string}
which is perfect for a unary type -CustomType
, and all you need to do is to make sure that the second parameter is a key of the unary type:keyof CustomType
as follows:Link to the TypeScript Playground.
Hopefully this is helpful!