justinkames / vuejs-logger

Provides customizable logging functionality for Vue.js. Compatible with Vue2.
MIT License
244 stars 50 forks source link

Property '$log' does not exist on type '*' #24

Closed sneko closed 4 years ago

sneko commented 6 years ago

Hi!

I'm using TypeScript with my Vue 2 project but after adding the vuejs-logger module and bound it to Vue I get the following error:

Property '$log' does not exist on type 'Application'.

That's the same for all my components... any idea how to solve this please?

Thanks

justinkames commented 6 years ago

Hi! Can you provide more code please? Makes the debugging easier.

Thanks!

sneko commented 6 years ago

I'm binding Vue to your plugin through:

Vue.use(VueLogger, {
  logLevel: process.env.VUE_APP_LOGGING_LEVEL,
  showConsoleColors: true,
});

And try to log with in a component

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

@Component({})
export default class Home extends Vue {
    public async create() {
      this.$log.info("Test");
    }
}
</script>

Using:

justinkames commented 6 years ago

Thanks, haven't tested it yet with typescript + vue-property-decorator. Let me check.

sneko commented 6 years ago

@justinkames any news please?

sneko commented 6 years ago

@justinkames keep me updated ;) thank you

jwhitmarsh commented 6 years ago

@sneko I solved this by extending the vue model myself

declare module 'vue/types/vue' {
  interface Vue {
    $log: {
      info(message: string, trace?: {}): void;
      warning(message: string, trace?: {}): void;
      error(message: string, trace?: {}): void;
    };
  }
}

I realise this is only a short term solution, but just in case you needed something immediately.

sneko commented 6 years ago

@jwhitmarsh thank you, I will give it a try 😃

sneko commented 6 years ago

@jwhitmarsh it doesn't work on my side.

    this.$log.error("Form error: ", error);

It's still unrecognized. Even worse, other plugins like "this.$validator" (vee-validate plugin) is not anymore valid 😢

jwhitmarsh commented 6 years ago

The info comes from here: https://vuejs.org/v2/guide/typescript.html#Augmenting-Types-for-Use-with-Plugins

I forgot to include that you have to import Vue so the whole file looks like:

// ./src/$log.d.ts
import Vue from 'vue';

declare module 'vue/types/vue' {
  interface Vue {
    $log: {
      info(message: string, trace?: {}): void;
      warning(message: string, trace?: {}): void;
      error(message: string, trace?: {}): void;
    };
  }
}

If you're using VSCode you might have to reload the window for it to pick up the declaration file.

I should also mention that I've stopped using vuejs-logger, so this declaration file is not complete. At a glance it's missing the debug and fatal methods, but also bear in mind that the log levels appear to be configurable, so you might need some dynamic typings.

sneko commented 6 years ago

@jwhitmarsh thank you!

Adding the import made it working. I just modified the functions signatures according to the plugin source code:

import Vue from 'vue';

declare module 'vue/types/vue' {
    interface Vue {
        $log: {
            debug(...args: any[]): void;
            info(...args: any[]): void;
            warn(...args: any[]): void;
            error(...args: any[]): void;
            fatal(...args: any[]): void;
        };
    }
}

Could you tell me why you stopped using this logger please? And which one did you choose to move on?

😃

jwhitmarsh commented 6 years ago

No worries, glad it's working :)

It was simply that our requirements changed - we need to post our logs to an API. I ended up creating my own very simple Plugin - I'm very grateful to @justinkames for his work with this because it is great to learn from. In the end we just needed something a bit more specific to our needs.

justinkames commented 6 years ago

@jwhitmarsh Thanks, happy to hear the plugin was usefull!

ryanleecode commented 5 years ago

@sneko solution almost worked for me. Had to change the interface to use the VueConstructor instead.

import Vue from 'vue';

declare module 'vue/types/vue' {
  export interface VueConstructor<V extends Vue = Vue> {
    $log: {
      debug(...args: any[]): void;
      info(...args: any[]): void;
      warn(...args: any[]): void;
      error(...args: any[]): void;
      fatal(...args: any[]): void;
    };
  }
}
AlvaroBrey commented 5 years ago

@justinkames would you consider adding such a .d.ts file in the NPM package, or publishing another package with type definitions? This is needed to properly use vuejs-logger in Typescript projects.

In the meantime we can all work around it by adding the definitions ourselves, but it would be better if we didn't have to.

garyo commented 5 years ago

I also needed this (I used exactly the @drdgvhbh solution with VueConstructor), in order to be able to use Vue.$log.debug() outside a component. Would be great if it were in the package!

fchu commented 5 years ago

Adding this here in case others find it useful. I actually fixed it by doing the following:

declare module 'vue-jslogger' {
    module "vue/types/vue" {
        interface VueConstructor<V extends Vue = Vue> {
            $log: {
                debug(...args: any[]): void;
                info(...args: any[]): void;
                warn(...args: any[]): void;
                error(...args: any[]): void;
                fatal(...args: any[]): void;
            };
        }
    }
}

My understanding (I'm new to Typescript) is that you want to declare the module for the, well, module you installed, here vue-jslogger and in it extend existing modules (the Vue one vue/types/vue should be installed already if you're reading this) with the correct interface so that vscode understands it. For instance the above does the trick if you're calling $log from the Vue instance directly by upgrading its constructor. If you're calling from within a Vue instance, add the declaration to the Vue interface directly.

justinkames commented 4 years ago

The d.ts file is now included in version 1.5.4 and ( 0964b185c6a92f234314b4bbcf83c8ac68ab155c )

AlvaroBrey commented 4 years ago

@justinkames Thanks for the type definitions! However, I'd like to request you extend the VueConstructor interface rather than the Vue interface, as outlined above by @fchu and @drdgvhbh.

The current type definitions allow using $log in a Vue instance, but they do not calling $log on the global Vue object, which would be solved by extending the constructor.

LissetteIbnz commented 4 years ago

You should check your tsconfig.json file because if you have the types property defined, you should include vuejs-logger.

hjelperne commented 4 years ago

Hi a bit of a newbie question here (new to typescript anyway..)

Could someone please shed some light as to how the declaration files (ref: are supposed to help?

Where exactly I am supposed to add a reference to the node_modules/vuejs-logger/dist/index.d.ts ? Or do I have to do something else entirely?

I have tried adding the following 2 files:

File 1: src/main/frontend-ts/vuejs-logger.d.ts Content File 1: declare module 'vuejs-logger'

File 2: src/main/frontend-ts/src/$log.d.ts Content File 2: declare module 'vue/types/vue' { export interface VueConstructor { $log: { debug(...args: any[]): void info(...args: any[]): void warn(...args: any[]): void error(...args: any[]): void fatal(...args: any[]): void }; } }

This makes vuejs-logger work at least - and makes the "eslint-errors" in main.ts go away

But I still get the following errors in my terminal console whenever I start npm run serve

`ERROR in src/main/frontend-ts/src/components/HelloWorld.vue(47,10): 47:10 Property '$log' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<{ msg: string; }>>'. 45 | }, 46 | mounted () {

47 | this.$log.debug('Mounted Home') | ^ 48 | } 49 | }) 50 | ERROR in src/main/frontend-ts/src/main.ts(25,5): 25:5 Property '$log' does not exist on type 'VueConstructor'. 23 | Vue.use(VueLogger, logOptions) 24 | 25 | Vue.$log.debug('Starting app - Production build mode: ', isProduction) | ^ 26 | 27 | new Vue({ 28 | router,`

I have also tried adding "vuejs-logger" to the types array in tsconfig.json without any luck: "types": [ "webpack-env", "mocha", "chai"; "vuejs-logger" ],

The project was setup brand new today with vue-cli @vue/cli 4.5.4

Relevant dependencies: "vue": "^2.6.11", "vuejs-logger": "1.5.4",

"devDependencies": { "@types/chai": "^4.2.11", "@types/mocha": "^5.2.4", "@typescript-eslint/eslint-plugin": "^2.33.0", "@typescript-eslint/parser": "^2.33.0", "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-e2e-cypress": "~4.5.0", "@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-plugin-router": "~4.5.0", "@vue/cli-plugin-typescript": "~4.5.0", "@vue/cli-plugin-unit-mocha": "~4.5.0", "@vue/cli-plugin-vuex": "~4.5.0", "@vue/cli-service": "~4.5.0", "@vue/eslint-config-standard": "^5.1.2", "@vue/eslint-config-typescript": "^5.0.2", "@vue/test-utils": "^1.0.3", "chai": "^4.1.2", "eslint": "^6.7.2", "eslint-plugin-import": "^2.20.2", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.0", "eslint-plugin-vue": "^6.2.2", "node-sass": "^4.12.0", "sass-loader": "^8.0.2", "typescript": "~3.9.3", "vue-template-compiler": "^2.6.11" }

Any help to clarify how to use the type definitions added in 0964b18 correctly is greatly appreciated!

AlvaroBrey commented 4 years ago

@hjelperne With vuejs-logger version 1.5.4 you shouldn't need to do any modification in order to use this.$log, at least in a standard vue-cli install. You can undo your changes.

However, in order to use $log on the Vue global, you will need to add this file:

src/main/frontend-ts/src/types/$log.d.ts

// noinspection ES6UnusedImports
import Vue from 'vue'
import {Log} from 'vuejs-logger'

/**
 * The vuejs-logger package only defines $log for the vue instance, not for the constructor.
 * As a result, there is no way to call the logger on the Vue global. This fixes that.
 */
declare module 'vue/types/vue' {
  export interface VueConstructor<V extends Vue = Vue> {
    $log: Log
  }
}

Aside from that, you should need no other modifications, neither new files nor changes to tsconfig.json.

hjelperne commented 4 years ago

Hi, @re2005 alvarobrey Thank you so much for the quick reply!!! I really appreciate the effort!

Unfortunately this did not help:

I removed everything Ive done previously - which leaves me with a newly created app with vue-cli:

vue create frontend-ts

I then added your suggested: src/main/frontend-ts/src/types/$log.d.ts -and pasted the exact contents (from above).

In my main ts I have: import VueLogger from 'vuejs-logger' // <- This is red in IntelliJ with warning "TS2307: Cannot find module 'vuejs-logger' or its corresponding type declarations.

I then have:

const isProduction = process.env.NODE_ENV === 'production'

// GLOBAL PLUGINS // Add vuejs-logger const logOptions = { isEnabled: true, logLevel: isProduction ? 'error' : 'debug', stringifyArguments: false, showLogLevel: true, showMethodName: true, separator: '|', showConsoleColors: true }

Vue.use(VueLogger, logOptions)

This is the only extension in a clean setup with vue cli

I still get the errors when npm run serve:

`$ npm run serve

frontend-ts@0.1.0 serve ~/src/main/frontend-ts vue-cli-service serve

INFO Starting development server... Starting type checking service... Using 1 worker with 2048MB memory limit 98% after emitting CopyPlugin

DONE Compiled successfully in 1262ms 17:14:28

Type checking in progress...

App running at:

ERROR in ../src/main/frontend-ts/src/components/HelloWorld.vue(47,10): 47:10 Property '$log' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<{ msg: string; }>>'. 45 | }, 46 | mounted () {

47 | this.$log.debug('Mounted Home') | ^ 48 | } 49 | }) 50 | ERROR in ../src/main/frontend-ts/src/main.ts(23,9): 23:9 No overload matches this call. Overload 1 of 2, '(plugin: PluginObject<{ isEnabled: boolean; logLevel: string; stringifyArguments: boolean; showLogLevel: boolean; showMethodName: boolean; separator: string; showConsoleColors: boolean; }> | PluginFunction<...>, options?: { ...; } | undefined): VueConstructor<...>', gave the following error. Argument of type 'typeof import("~/src/main/frontend-ts/node_modules/vuejs-logger/dist/index")' is not assignable to parameter of type 'PluginObject<{ isEnabled: boolean; logLevel: string; stringifyArguments: boolean; showLogLevel: boolean; showMethodName: boolean; separator: string; showConsoleColors: boolean; }> | PluginFunction<...>'. Property 'install' is missing in type 'typeof import("~/src/main/frontend-ts/node_modules/vuejs-logger/dist/index")' but required in type 'PluginObject<{ isEnabled: boolean; logLevel: string; stringifyArguments: boolean; showLogLevel: boolean; showMethodName: boolean; separator: string; showConsoleColors: boolean; }>'. Overload 2 of 2, '(plugin: PluginObject | PluginFunction, ...options: any[]): VueConstructor', gave the following error. Argument of type 'typeof import("~/src/main/frontend-ts/node_modules/vuejs-logger/dist/index")' is not assignable to parameter of type 'PluginObject | PluginFunction'. Property 'install' is missing in type 'typeof import("~/src/main/frontend-ts/node_modules/vuejs-logger/dist/index")' but required in type 'PluginObject'. 21 | } 22 | 23 | Vue.use(VueLogger, logOptions) | ^ 24 | 25 | Vue.$log.debug('Starting Tella - Production build mode: ', isProduction) 26 | Version: typescript 3.9.7 Time: 1476ms ` PS: the logging is working (the staements from main.ts and Home.vue are showing up in the console - just VERY annoying getting these long errors on every npm run serve ..

Any other suggestions??

AlvaroBrey commented 4 years ago

Here's some working code for main.ts:

import { ILoggerOptions } from 'vuejs-logger/dist/interfaces/logger-options'
import { PluginObject } from 'vue'
import { LogLevels } from 'vuejs-logger/dist/enum/log-levels'

const isProduction = process.env.NODE_ENV === 'production'
const logOptions: ILoggerOptions = {
  isEnabled: true,
  logLevel: isProduction ? LogLevels.ERROR : LogLevels.DEBUG,
  stringifyArguments: false,
  showLogLevel: true,
  showMethodName: true,
  separator: '|',
  showConsoleColors: true
}
const loggerPlugin = (VueLogger as unknown) as PluginObject<ILoggerOptions>
Vue.use<ILoggerOptions>(loggerPlugin, logOptions)

Still checking why this.$log won't work.

hjelperne commented 4 years ago

Hi - thanks again.

I have now updated main.ts accordingly. Your suggested changes still has my import: import VueLogger from 'vuejs-logger' marked in red in IntelliJ.. with same warning "TS2307: Cannot find module 'vuejs-logger' or its corresponding type declarations." Until I added back the file: src/main/frontend-ts/vuejs-logger.d.ts with contents: declare module 'vuejs-logger'

Now my error in console on startup is reduced to:

ERROR in ~/src/main/frontend-ts/src/components/HelloWorld.vue(47,10): 47:10 Property '$log' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<{ msg: string; }>>'. 45 | }, 46 | mounted () {

47 | this.$log.debug('Mounted Home') | ^ 48 | } 49 | }) 50 | Version: typescript 3.9.7

Very strange...

AlvaroBrey commented 4 years ago

@hjelperne I do not know why TS isn't picking up the types (it does in my other project, but not in a fresh one), but here's a workaround: change $log.d.ts to the following:

// noinspection ES6UnusedImports
import Vue from 'vue'
import { Log } from 'vuejs-logger'

/**
 * The vuejs-logger package only defines $log for the vue instance, not for the constructor.
 * As a result, there is no way to call the logger on the Vue global. This fixes that.
 */
declare module 'vue/types/vue' {
    interface Vue {
        $log: Log;
      }
    export interface VueConstructor<V extends Vue = Vue> {
        $log: Log;
    }
}
hjelperne commented 4 years ago

Thank you very much indeed! No type errors found!

I do have to leave in the file: src/main/frontend-ts/vuejs-logger.d.ts to prevent the aformentioned "red" notice in main.ts relating to the import: import VueLogger from 'vuejs-logger'

But besides that everything appears to be working as it should - thank you again - I would have probably given up if it wasnt for your superbe assistance!

Perhaps one should suggest updating the docs or something - I mean this is pretty far from what the docs state..

Best regards!

PS - By the way:

I replaced your main.ts lines const loggerPlugin = (VueLogger as unknown) as PluginObject<ILoggerOptions> Vue.use<ILoggerOptions>(loggerPlugin, logOptions) back to: Vue.use(VueLogger, logOptions)

and everything appears to still be working as expected! Forever grateful.

marabunta62 commented 3 years ago

To recap, this thread has helped me a lot to apply this package:

$log.d.ts content :

// noinspection ES6UnusedImports
import Vue from 'vue'
import { Log } from 'vuejs-logger'

/**
 * The vuejs-logger package only defines $log for the vue instance, not for the constructor.
 * As a result, there is no way to call the logger on the Vue global. This fixes that.
 */
declare module 'vue/types/vue' {
    interface Vue {
        $log: Log;
    }
    export interface VueConstructor<V extends Vue = Vue> {
        $log: Log
    }
}

vuejs-logger.d.ts content: declare module 'vuejs-logger';

main.ts content:

import VueLogger from 'vuejs-logger';
const isProduction = process.env.NODE_ENV === 'production';

// GLOBAL PLUGINS
// Add vuejs-logger
const logOptions = {
    isEnabled: true,
    logLevel: isProduction ? 'error' : 'debug',
    stringifyArguments: false,
    showLogLevel: true,
    showMethodName: true,
    separator: '|',
    showConsoleColors: true
};

Vue.use(VueLogger, logOptions);