Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Member 'XXX' implicitly has an 'any' type. #58

Open
seiwhale opened this issue Nov 22, 2019 · 3 comments
Open

[Bug]: Member 'XXX' implicitly has an 'any' type. #58

seiwhale opened this issue Nov 22, 2019 · 3 comments

Comments

@seiwhale
Copy link

I am trying to use @State in my vue component, but Vetur gives a hint: Member 'XXX' implicitly has an 'any' type.Vetur(7008).

image

code like this:

// store.ts
state: {
    switchFlg: false,
},

// my component
@State private switchFlg;

I know it needs declaration type, and I can fix it by @State switchFlg!: boolean;. But I think it's too troublesome, I have to write the declaration type twice, or even more.

Is there a better solution?

@vegerot
Copy link

vegerot commented Mar 25, 2020

It gets even trickier with Actions, Getters, and Mutations. No I have to do things like

import { ActionMethod } from 'vuex';
import { Action, Getter, State } from 'vuex-class';
...
  @Action('fetchRequirements', { namespace: 'requirements' }) private fetchRequirements!: ActionMethod;

But when I import ActionMethod from Vuex I get warnings in vue-cli-service serve and webpack saying

 warning  in ./src/components/file.vue?vue&type=script&lang=ts&

"export 'ActionMethod' was not found in 'vuex'

@humodz
Copy link

humodz commented Apr 10, 2020

I don't think it's possible for the directive itself enforce the type of the decorated property, but one workaround is using the StateType['nameOfTheField] syntax instead of hardcoding the type in the component:

interface RootState {
  myField: string
}

@Component
export default class MyComponent extends Vue {
  @State public myField!: RootState['myField'];
}

This way, if the type of RootState.myField is changed, the compiler is able to warn you everywhere it is used.

It's still a bit verbose and I don't think it covers every use case, but at least it's easier to check for correctness, since you just have to be sure that the name of the attribute (or the string passed to @State) matches the field of the type.

For type-safe actions and mutations, I'm using two helper types, but to be able to use them the actions and mutations have to be declared in a specific way:

// Usage
@Component
export default class MyComponent extends Vue {
  @State public myField!: RootState['myField'];
  @Action public myAction: ActionFn<typeof actions.myAction>;
  @Mutation public myMutation: MutationFn<typeof mutations.myMutation>;

  async doStuff() {
    // these are type-safe, passing the wrong argument types results in a compiler error
    this.myMutation(123);
    await this.myAction('some text');
  }
}

// Declarations
export type MutationFn<T extends Mutation<any>> =
  Parameters<T>[1] extends undefined
    ? () => void
    : (arg: Parameters<T>[1]) => void;

export type ActionFn<T extends ActionHandler<any, any>> =
  Parameters<T>[1] extends undefined
    ? () => Promise<void>
    : (arg: Parameters<T>[1]) => Promise<void>;

interface RootState {
  myField: string;
}

// Note: actions must not be typed as ActionTree, otherwise
// typescript won't be able to infer the actions that exist in
// "typeof actions.myAction"
export const actions = {
  myAction(context: ActionContext<RootState, RootState>, text: string) { /* ... */ },
};

// Ditto for MutationTree
export const mutations = {
  myMutation(state: RootState, someNumer: number) { /* ... */ },
};

export const store: StoreOptions<RootState> = {
  state: { myField: 'hello' },
  actions,
  mutations,
};

I hope this can be of use

@vegerot
Copy link

vegerot commented Aug 14, 2020

I don't know how I've been so stupid about this for so long.

@seiwhale @humodz just say

import type { ActionMethod } from 'vuex';

type imports are removed by the compiler, and is better practice anyways

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants