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

Add .d.ts for typescript like vuex #26

Open
henrixapp opened this issue May 24, 2018 · 3 comments
Open

Add .d.ts for typescript like vuex #26

henrixapp opened this issue May 24, 2018 · 3 comments
Assignees

Comments

@henrixapp
Copy link

henrixapp commented May 24, 2018

Adding a index.d.ts would be great in order to support typescript. I have drafted one already, based on the vuex one:

declare module 'vuex-map-fields' {
import _Vue, { WatchOptions } from "vue";

// augment typings of Vue.js


export  class Store<S> {
  constructor(options: StoreOptions<S>);

  readonly state: S;
  readonly getters: any;

  replaceState(state: S): void;

  dispatch: Dispatch;
  commit: Commit;

  subscribe<P extends MutationPayload>(fn: (mutation: P, state: S) => any): () => void;
  watch<T>(getter: (state: S) => T, cb: (value: T, oldValue: T) => void, options?: WatchOptions): () => void;

  registerModule<T>(path: string, module: Module<T, S>, options?: ModuleOptions): void;
  registerModule<T>(path: string[], module: Module<T, S>, options?: ModuleOptions): void;

  unregisterModule(path: string): void;
  unregisterModule(path: string[]): void;

  hotUpdate(options: {
    actions?: ActionTree<S, S>;
    mutations?: MutationTree<S>;
    getters?: GetterTree<S, S>;
    modules?: ModuleTree<S>;
  }): void;
}

export  function install(Vue: typeof _Vue): void;

export interface Dispatch {
  (type: string, payload?: any, options?: DispatchOptions): Promise<any>;
  <P extends Payload>(payloadWithType: P, options?: DispatchOptions): Promise<any>;
}

export interface Commit {
  (type: string, payload?: any, options?: CommitOptions): void;
  <P extends Payload>(payloadWithType: P, options?: CommitOptions): void;
}

export interface ActionContext<S, R> {
  dispatch: Dispatch;
  commit: Commit;
  state: S;
  getters: any;
  rootState: R;
  rootGetters: any;
}

export interface Payload {
  type: string;
}

export interface MutationPayload extends Payload {
  payload: any;
}

export interface DispatchOptions {
  root?: boolean;
}

export interface CommitOptions {
  silent?: boolean;
  root?: boolean;
}

export interface StoreOptions<S> {
  state?: S;
  getters?: GetterTree<S, S>;
  actions?: ActionTree<S, S>;
  mutations?: MutationTree<S>;
  modules?: ModuleTree<S>;
  plugins?: Plugin<S>[];
  strict?: boolean;
}

type ActionHandler<S, R> = (injectee: ActionContext<S, R>, payload: any) => any;
interface ActionObject<S, R> {
  root?: boolean;
  handler: ActionHandler<S, R>;
}

export type Getter<S, R> = (state: S, getters: any, rootState: R, rootGetters: any) => any;
export type Action<S, R> = ActionHandler<S, R> | ActionObject<S, R>;
export type Mutation<S> = (state: S, payload: any) => any;
export type Plugin<S> = (store: Store<S>) => any;

export interface Module<S, R> {
  namespaced?: boolean;
  state?: S | (() => S);
  getters?: GetterTree<S, R>;
  actions?: ActionTree<S, R>;
  mutations?: MutationTree<S>;
  modules?: ModuleTree<R>;
}

export interface ModuleOptions{
  preserveState?: boolean
}

export interface GetterTree<S, R> {
  [key: string]: Getter<S, R>;
}

export interface ActionTree<S, R> {
  [key: string]: Action<S, R>;
}

export interface MutationTree<S> {
  [key: string]: Mutation<S>;
}

export interface ModuleTree<R> {
  [key: string]: Module<any, R>;
}

 const _default: {
  Store: typeof Store;
  install: typeof install;
}
type Dictionary<T> = { [key: string]: T };
type Computed = () => any;
type MutationMethod = (...args: any[]) => void;
type ActionMethod = (...args: any[]) => Promise<any>;

interface Mapper<R> {
  (map: string[]): Dictionary<R>;
  (map: Dictionary<string>): Dictionary<R>;
}

interface MapperWithNamespace<R> {
  (namespace: string, map: string[]): Dictionary<R>;
  (namespace: string, map: Dictionary<string>): Dictionary<R>;
}

interface FunctionMapper<F, R> {
  (map: Dictionary<(this: typeof _Vue, fn: F, ...args: any[]) => any>): Dictionary<R>;
}

interface FunctionMapperWithNamespace<F, R> {
  (
    namespace: string,
    map: Dictionary<(this: typeof _Vue, fn: F, ...args: any[]) => any>
  ): Dictionary<R>;
}

interface MapperForState {
  <S>(
    map: Dictionary<(this: typeof _Vue, state: S, getters: any) => any>
  ): Dictionary<Computed>;
}

interface MapperForStateWithNamespace {
  <S>(
    namespace: string,
    map: Dictionary<(this: typeof _Vue, state: S, getters: any) => any>
  ): Dictionary<Computed>;
}

interface NamespacedMappers {
  mapState: Mapper<Computed> & MapperForState;
  mapMutations: Mapper<MutationMethod> & FunctionMapper<Commit, MutationMethod>;
  mapFields: Mapper<Computed>;
  mapActions: Mapper<ActionMethod> & FunctionMapper<Dispatch, ActionMethod>;
}

export  const mapState: Mapper<Computed>
  & MapperWithNamespace<Computed>
  & MapperForState
  & MapperForStateWithNamespace;

export  const mapMutations: Mapper<MutationMethod>
  & MapperWithNamespace<MutationMethod>
  & FunctionMapper<Commit, MutationMethod>
  & FunctionMapperWithNamespace<Commit, MutationMethod>;

export  const mapGetters: Mapper<Computed>
  & MapperWithNamespace<Computed>;

export  const mapActions: Mapper<ActionMethod>
  & MapperWithNamespace<ActionMethod>
  & FunctionMapper<Dispatch, ActionMethod>
  & FunctionMapperWithNamespace<Dispatch, ActionMethod>;

interface HelperOptions{
  getterType: string;
  mutationType:string
}
export  function createHelpers(helperOptions:HelperOptions): NamespacedMappers;

export default _default;
}

Probably the unused types should be removed. Currently it just enables correct typing with createHelpers

@maoberlehner
Copy link
Owner

Hey @henrixapp I appreciate your work and from using TypeScript myself for certain projects, I know how nice it is to have the correct types for all of your dependencies.

But what concerns me is this: the types have to be updated every time I make some changes – and to be completely honest with you: I don't want to invest my time in that. It even gets more complicated if other people decide to contribute their time, I can't expect every contributor to be familiar with TypeScript.

So I decided against adding types in this repository. I'm sorry.

But I'd be very happy if you (or anyone else) decides to invest some time and add vuex-map-fields to https://github.com/DefinitelyTyped/DefinitelyTyped

Thx for contributing!

@vemmkof
Copy link

vemmkof commented Nov 30, 2019

The other way to add v-m-f with ts is:

import Vue from "vue";
import Vuex from "vuex";
const vuexMapFields = require("vuex-map-fields");
const getField = vuexMapFields.getField;
const updateField = vuexMapFields.updateField;
Vue.use(Vuex);

export default new Vuex.Store({
  state: {},
  getters: { getField },
  mutations: { updateField },
  actions: {},
  modules: {}
});

@mchl18
Copy link

mchl18 commented Apr 13, 2021

Hey @maoberlehner !

It seems there is a simpler way to get typings in than to add them to DefinitelyTyped, which has its whole own process and standards.

Instead it is recommended by them that, if there is a way to generate these automatically, to just add them to the npm repo:

If you are the library author and your package is written in TypeScript, bundle the autogenerated declaration files in your package instead of publishing to Definitely Typed.

source: https://github.com/DefinitelyTyped/DefinitelyTyped#create-a-new-package

However this can also be done with JS. For generating these typings we just need to add typescript to the devDependencies and add a step in the build scripts which runs typescript with a special config. After that, the type definitions will be provided simply from within the folder node_modules/vuex-map-fields/types instead of node_modules/@types/vuex-map-fields, which I believe is much simpler. We just reference that folder in the package.json

All of which has been done here:

#137

The auto-generated typings are currently not really the most precise as they will just default to any in most cases. I believe it is possible to add and precisely generate these via jsDoc somehow, which is something which would need to be done in order to serve meaningful types. That is something which has not been done in this PR yet.

This PR way however avoids needing to create a shim d.ts to avoid errors when the vue project has been set up with typescript, so I would argue it is a step into the right direction.

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

No branches or pull requests

4 participants