The Humble Colon: Destructuring + Type Annotations in Typescript

The problem

I use the great Vuex along with Typescript for state management in a Vue app. One day I spotted a nasty bug caused by the overloaded meaning of : in Typescript. Here's the kind of thing I was doing:

const state = { ... };

export const actions = {  
  doSomething({ commit, state: MyStateType }, payload: SomePayloadType) {
    ...
  }
};

Now, here I'm trying to say that the state property of the function parameter has a type of MyStateType. However, in ES2015 nested destructuring goes like this (example courtesy of MDN):

var metadata = {  
    title: 'Scratchpad',
    translations: [
       {
        locale: 'de',
        localization_tags: [],
        last_edit: '2014-04-14T08:43:37',
        url: '/de/docs/Tools/Scratchpad',
        title: 'JavaScript-Umgebung'
       }
    ],
    url: '/en-US/docs/Tools/Scratchpad'
};

var {title: englishTitle, translations: [{title: localeTitle}]} = metadata;  

In ES2015, the : is already used to specify nested destructuring, so it can't be used in Typescript as a type annotation.

So what the code above actually ends up doing is defining a variable called 'MyStateType' with the value of 'state' from the parameter. But the code compiles fine??!

Because I've also defined a variable called state in the enclosing scope (used to populate the initial state in the Vuex store), the code in the action function unintentionally ends up referring to this object from the outer scope, NOT the state object passed into the function itself. Nasty! But nobody is any the wiser...

The solution

Besides religiously using different variable names in different scopes, the way to achieve what I actually wanted in the first place is a bit messy, but works. We define a type for the parameters being passed in - we could do inline, but it's the same for all of the actions. We then destructure inside the function itself, effectively separating the destructuring and type annotation into two steps. The result looks like this:

const initialState = { ... };  
type ActionParameters = { commit: any, state: MyStateType, getters: MyGettersType };

export const actions = {  
  doSomething(params: ActionParameters, payload: SomePayloadType) {
    const { commit, state, getters } = params;
    ...
  }
};

Thanks to Jaime González for the pointer, and ultimately Anders Hejlsberg for the solution.