7

I have following code and I would like to pass number from value key of variable object, How can I use variable for optional chaining operator for it to solve the error Element implicitly has an any type?

    function fun(i?: number) {
        console.log(i)
    }

    const variable = { min: { value: 1, name: 'google' }, max: {value: 2, name: 'apple'} }
    const variable2 = { min: { value: 1, name: 'google' } }
    const variable3 = { max: {value: 2, name: 'apple'} }

    fun(variable?.min.value) // working => 1
    fun(variable?.max.value) // working => 2
    fun(variable2?.min.value) // working => 1
    fun(variable2?.max.value) // working => undefined
    fun(variable3?.min.value) // working => undefined
    fun(variable3?.max.value) // working => 2

    Object.keys(variable).forEach((key) => {
        fun(variable?.[key]?.value) // working but with error Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ min: { value: number; name: string; }; max: { value: number; name: string; }; }'.
    })
7
  • github.com/microsoft/TypeScript/issues/13254 Commented Jul 31, 2020 at 23:19
  • .[key] looks like invalid syntax. Given that you are getting the key by looping over the variable, the variable has to exist. variable[key] should always be valid in the forEach Commented Jul 31, 2020 at 23:19
  • 2
    @Taplar it's not .[key] it's ?.[key], it's a new composite operator. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Jul 31, 2020 at 23:20
  • ? there isn't the safety operator? Commented Jul 31, 2020 at 23:20
  • @Taplar it's a ?.[] operator, optional chaining + indexing. Commented Jul 31, 2020 at 23:21

1 Answer 1

5

This isn't actually an optional chaining problem, but a problem with how Object.keys works. Typescript assumes that an object may have more keys than is known at compile time so the type of key here is string and not keyof variable. To get around that you would have to let the TS compiler know that all the keys are known at compile time using

Object.keys(variable).forEach((key) => {
  fun(variable[key as keyof typeof variable].value) 
})

You're already treating variable as a non-null variable when you use it in Object.keys so there's no need to additionally use optional chaining on it. Additionally, when you cast key into keyof typeof variable, you're asserting that it already exists so you can remove the optional chaining before ?.value as well.

Sign up to request clarification or add additional context in comments.

1 Comment

OK, so how would you do something like variable && Object.keys(variable).length>1? If it were a method on the object, it would be variable?.keys().length > 1 but it isn't...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.