2

This is my ts code.

const actions = {
    APPROVE: Symbol('APPROVE'),
    SCHEDULE: Symbol('SCHEDULE'),
}

const obj = {
    [actions.APPROVE]: ({ amount }: {amount: number}) => {
        return `test`
    },
    [actions.SCHEDULE]: () => {
        return `test`
    },
}

console.log(obj[actions.SCHEDULE as any]())

The above code produces the following error: Expected 1 arguments, but got 0.

I don't know why it tries to get APPROVE instead of SCHEDULE.

Any idea ?

UPDATE: Just got rid of Symbol, but the problem is exactly the same.

here is the updated code:

const actions = {
    APPROVE: 'APPROVE',
    SCHEDULE: 'SCHEDULE'
}

const obj = {
    [actions.SCHEDULE]: () => {
        return `Schedules a new Proposal`
    },
    [actions.APPROVE]: ({ amount }: {amount: number}) => {
        return `Approves ${amount} ANT`
    }
}

console.log(obj[actions.SCHEDULE]())
5
  • 2
    You have 2 functions in there, one takes 0 arguments, the other takes 1 argument. You have typed the key as any - typescript has no idea what value an any key will yield, so it returns a union type - a function that takes 1 argument or a function that takes 0 arguments. There's no way to call this without first asserting which function that actually is. Since 0 != 1. Commented May 4, 2021 at 14:12
  • Of course, the primary issue here is typescript's inability to use symbol as an index type. This is supposed to be made available in the near future. Currently however, using custom symbol types as object keys is not the best of ideas. Commented May 4, 2021 at 14:12
  • so, no way to fix this problem in typescript, right ? Commented May 4, 2021 at 14:13
  • That ^^^ its still the SCHEDULE function being invoked Commented May 4, 2021 at 14:13
  • 1
    Related PR: github.com/microsoft/TypeScript/pull/26797 Commented May 4, 2021 at 14:15

2 Answers 2

4

TypeScript simply does not support using Symbols as object keys like that. There's an issue about this with more details about why and possibly when this might be supported.

The only reason your code compiles is that you used as any, but the moment you do that TypeScript can no longer discriminate between each value of the object based on the key, so it returns a union type which is valid for both, which is the one with one parameter.

Use strings for object keys instead and it'll work.

BTW, this is not a runtime error, but a TypeScript compiler error.

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

2 Comments

removing Symbol causes the same problem.
But now you are trying to use a variable to access an object property. TypeScript cannot guarantee that actions.SCHEDULE won't be FOOBARBAZ at runtime, so it cannot discriminate either. My suggestion was to use strings directly, as in obj = { SCHEDULE: () ... } and then obj['SCHEDULE'] or obj.SCHEDULE.
1

Make the amount optional, so that both functions have the same type and call the SCHEDULE with ({}):

const obj = {
    [actions.SCHEDULE]: () => {
        return `Schedules a new Proposal`
    },
    [actions.APPROVE]: ({ amount }: {amount?: number}) => {
        return `Approves ${amount} ANT`
    }
}

console.log(obj[actions.SCHEDULE]({}))

..or even easier:

const obj = {
    [actions.SCHEDULE]: () => {
        return `Schedules a new Proposal`
    },
    [actions.APPROVE]: (amount?: number) => {
        return `Approves ${amount} ANT`
    }
}

console.log(obj[actions.SCHEDULE]())
console.log(obj[actions.APPROVE](6))

Comments

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.