Use string to access properties of a readonly object in typescript

391 Views Asked by At
const parent2 = {child: 'name'}
const index2: string = 'child';
const child3 = parent2[index2]

When I try to access child in parent2 I get the following error

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ child: string; }'.
  No index signature with a parameter of type 'string' was found on type '{ child: string; }'

Is there an easy way to make parent2[index2] return 'name' | undefined ?

It's even more difficult to deal with nested readonly object. allowStringIndex type keeps index autocomplete and it allows accesing properties using string, but it's annoying to construct the type. Is there an easy way to access nestedObject[grandParentIndex]?.[parentIndex]

const nestedObject = {grandParent: {name: 'grandparent', parent: {name: 'parent', child: {name: 'child'}}}} as const;
type child = {name: 'child', [key: string]: 'child' | undefined}
type parent = {name: 'parent', child: child}
type overrideParent = parent & {[key: string]: parent[keyof parent] | undefined}
type grandParent = {name: 'grandparent', parent: overrideParent}
type overrideGrandParent= grandParent & {[key: string]: grandParent[keyof grandParent] | undefined}

type allowStringIndex = {grandParent: overrideGrandParent} & {[key: string]: overrideGrandParent | undefined}

const castedObject = nestedObject as allowStringIndex;
const grandParentIndex: string = 'grandparent';
const parentIndex: string = 'parent'

const child = nestedObject[grandParentIndex]?.[parentIndex]?.['child']
const parent1 = castedObject[grandParentIndex]?.[parentIndex]

https://www.typescriptlang.org/play?ssl=19&ssc=31&pln=1&pc=1#code/MYewdgzgLgBGCm14BMDyAjAVvYsC8MA3gOYBOAhmMgArmnxhQBcRY5AtvCwORmXIAHOgyjcANDCH1GLQm048pI8TGAALAJYAbZLPlcY3dduTcAvhbMxyEVeGgBuAFBQAngPirNOmATkcDI29TCQBtAGt4VxZoUg0wYgBdHmMdbhgAHxgAVyp4ADN4lDMXd08lRl9WAMVhRhVU3S8TErcPGBAAN3hSOOR4Wml8STrYADIiCKiYqDiE5JGhqdcQfMWRRMycvMKEZFaymD4qQZEq-wVDY8FRlQrmDu7ejX7TxgP2rp6++ABxChOowI1ze40mkWiMFi8SSLBBo2WqyOAJoo02WVy-V2xScpXa5C0WhAAHcAMqzGEASTyAA9zvChiwvs9+v9+KCrBNCMsZnNYY9vi8-ijQVtMQUivtcaBILBgDYoCgMNhcFUEEg0FgcLAbNZCSTyXzqf0ac4ZdBkezRsb4DTeTCqrwUfduGb7LB7ja7VCKQlHS7pe7mj4COrFZqVVBQgyRF7EgB+AB0oU9tITyaCJm4iSc5o9owAjFV5RrldroyLrWmkymqyac7mg-cAEznRo8fTmRuymDxE3N+1+giZtJunuNADMVRboT7tubDaAA

Recursive type doesn't work perfectly https://www.typescriptlang.org/play?ts=4.9.4#code/MYewdgzgLgBGCm14BMDyAjAVvYsC8MA3gOYBOAhmMgArmnxhQBcRY5AtvCwORmXIAHOgyjcANDCH1GLQm048pI8TGAALAJYAbZLPlcY3dduTcAvhbMxyEVeGgBuAFAuoATwHwYAQS1aQAO4AylCkGmDEAJJU8AAeADwAsuQCnmhYOLBxUAzItkEArqkgpDnp2LgSAGrkWgXwACoeXgTQYREwAD5wBezo8KQShcWlKBgV+NZgbgB8MHhOMDDJqWMZuDDZubaEMADaANbwbjDhMEduIABmyylp45kAuiw1dY3NMFYA-ItLRPsXU5gc7Ha63VblJ4sFb3dZQQ7HR6fGAAMn+CLcLDa4WIz3BsImGLBMLWEyR3QKMSu4RQn1+S1kAOOQJBlxuJMhuDxvn8wVCOOiyDiSTupMyGMecysaN2GKx-Ii3L8gRC7SiMQSHIeuCJ7NFnKgkq6MEpQupCGQdJcoEgsGANjK2smCCQBusth5KoV6qFCXcnjBLsdcJmzicNugkmEjH081UDrFuAAdHwqLRpFAk0pGEn9OH7LBUzRo1BBXF5Wq47wKFRs6J87aoxmy7EKziq3XuA3I3WAIxx+2up17IvpkQtx5fJN7OsTlxOIA

1

There are 1 best solutions below

1
jered On

Why are you explicitly typing your string consts with : string instead of letting TypeScript infer the value? You can just remove those. Also, you seem to have misspelled the string assigned to grandParentIndex, it should be "grandParent" not "grandparent"?

// Don't do this
const parentIndex: string = 'parent'

// Do this
const parentIndex = 'parent';