Issue related to import/export with typings - javascript

I have JS file and want to write typings for it.
import { ApiService } from './src/ApiService'
Then I write typings and export it
export declare class ApiService {
constructor(adapter: any, options: any);
on:(evt, cb) => any;
extend: (opts) => any;
}
error TS2440: Import declaration conflicts with local declaration of ApiService
How can I fix It?

Put your declaration in a file ApiService.d.ts (but the keyword declare is unnecessary):
// src/ApiService.d.ts
export class ApiService {
constructor(adapter: any, options: any);
on:(evt, cb) => any;
extend: (opts) => any;
}
Notice that the TS definition file name must be the same as the JavaScript file name: ApiService.d.ts describes a JavaScript file ApiService.js.
Then, import it:
// test.ts
import { ApiService } from './src/ApiService'
It should works.

Related

How to declare a JS mixin for vue?

I'm writting a vue project with typescript and I want to use a mixin from thrid-part library which write by javascript, how to write a .d.ts to make ts can find function define in the mixin?
I tried this way and it not working:
// common.d.ts
declare module 'thrid-part-lib' {
import { VueClass } from 'vue-class-component/lib/declarations';
export interface SomeMixin<T> extends VueClass<T> {
refresh(): Promise<void>;
}
}
// index.ts
import { Component, Mixins } from 'vue-property-decorator';
import { SomeMixin } from 'thrid-part-lib';
#Component
export default class Index extends Mixins(SomeMixin) {
public foo() {
this.refresh(); // 'refresh' is not define.
}
}
You can augment a third party mixin with creating a file like vuelidate-error-extractor.d.ts:
declare module 'vuelidate-error-extractor' {
import { ValidationRule } from 'vuelidate/lib/validators';
// eslint-disable-next-line #typescript-eslint/class-name-casing
export class singleErrorExtractorMixin extends Vue {
readonly events: any;
readonly name: string;
readonly isValid: boolean;
readonly hasErrors: boolean;
readonly preferredValidator: ValidationRule;
}
}
This augments this JS file, but in an incomplete manner.
This is documented in "Augmenting Types for Use with Plugins".
Put this in a .d.ts file in your project to add a refresh() mixin method to components:
// 1. Make sure to import 'vue' before declaring augmented types
import Vue from 'vue'
// 2. Specify a file with the types you want to augment
// Vue has the constructor type in types/vue.d.ts
declare module 'vue/types/vue' {
// 3. Declare augmentation for Vue
interface Vue {
refresh(): void;
}
}

how to convert to import/export module's syntax by TypeScript global module

I want to convert older project's typescript code, for example:
// dataService.ts
module ProjectNs.Models {
export class DataService {
props1: string;
constructor(
private service: ProjectNs.Service.MyInjectService
) { }
}
}
it's equal global variable's method. now, I want to use webpack, and like es6 module syntax. for example:
// dataService.ts
export class DataService {
props1: string;
constructor(
private service: ProjectNs.Service.MyInjectService
) { }
}
// main.ts
import {DataService} from './dataService';
class Main {
}
There are so many TypeScript File, so, Is there any tool for batch conversion?

Export function as "root" of module?

When writing a TypeScript definition, how do you declare that the definition defines a function, rather than a type? So that the function is exported as the module itself...
Definition
declare module "rmdir" {
interface IRmDirCallback {
(err: any, dirs: Array<string>, files: Array<string>): any;
}
function rmdir(dir: string, options: any, callback: IRmDirCallback): void;
export = rmdir;
}
export = rmdir.rmdir;
Usage Example
/// <reference path="rmdir.d.ts"/>
import rmdir = require("rmdir");
rmdir("test", { }, (err: any, dirs: Array<string>, files: Array<string>) => { });
So when I import rmdir, I dont' want to have to call rmdir.rmdir(...).
Use export =. Here is the complete code:
declare module "rmdir" {
function rmdir(dir: string, options: any, callback: (err: any, dirs: Array<string>, files: Array<string>) => any): void;
export = rmdir;
}

How to import Javascript file into Typescript

I was wondering how I start the Twitter-Bootstrap from Typescript.
$('.carousel').carousel()
I had to implement jquery.d.ts to fix the $-sign call, but then I'm still getting the error that .carousel() could not be found in jquery.d.ts.
I tried to do this with bundling the javascript to a module and call it like that. But it does not seem to work.
This is my code:
carousel.d.ts
declare module 'carousel/carousel' {
var start: any;
export = start;
}
carousel.js
System.register('carousel/carousel', [], true, function () {
var carousel = function () {
function carousel() {
}
carousel.prototype.start = function () {
$('.carousel').carousel();
}
}
exports.carousel = carousel;
});
app.ts
import {Component} from "angular2/core";
import {bootstrap} from 'angular2/platform/browser';
import {Carousel} from "carousel/carousel";
#Component({
selector: "carousel",
bindings: [CarouselComponent],
templateUrl: 'carousel.html'
})
export class CarouselComponent {
start() {
carousel.start();
}
}
}
bootstrap(CarouselComponent)
Thanks for helping out.
The problem is that you don't have the typing definition for carousel(). Like you mentioned - it's a function in Twitter-Bootstrap, but you only included the typing definitions (*.d.ts) for jQuery. You need to include them for Bootstrap the same way.
You can get the full Bootstrap tying definitions from the DefinitelyTyped project, either from their GitHub or as a NuGet package. Here are the essential parts:
interface CarouselOptions {
interval?: number;
pause?: string;
wrap?: boolean;
keybord?: boolean;
}
interface JQuery {
carousel(options?: CarouselOptions): JQuery;
carousel(command: string): JQuery;
}
I would refactor your carousel.js file like this:
System.register("carousel/carousel", [], true, function(require, exports, module) {
var carousel = function () {
function carousel() {
}
carousel.prototype.start = function () {
$('.carousel').carousel();
}
}
exports.carousel = carousel;
});
Create a file "jquery-caroussel.d.ts" (and add-it to your reference.ts)
inside it:
interface JQuery {
carousel();
}
It will say to the ts compilator than there is a methode carousel() which will be implemented later. (in the browser, by the carousel.js file.)
If you have a similar issue with another lib than carousel, there is plenty of sample of interface here:https://github.com/DefinitelyTyped/DefinitelyTyped
You can import JS files by declaring an ambient module for each library you need. You can have an ambient.d.ts file where you store all ambient module declarations (ie for JavaScript libraries you'd like to import, but for which you do not have the type definitions)
ambient.d.ts:
// You would have a separate module declaration for each JavaScript library
// you want to import for which you do not have any type definitions
declare module 'my-module-i-want-to-import' {
const a : any;
export default a;
}
any other *.ts file that needs my-module-i-want-to-import:
// Include reference to your ambient module declarations
///<reference path="./ambient.d.ts" />
import myModule from 'my-module-i-want-to-import';
// Do something with myModule
console.log(myModule);
In the end, I've changed my code to use the "InjectionToken".
As described here: Use jQuery in Angular/Typescript without a type definition
You can simply inject the jQuery global instance and use it. For this you won't be needing any type definitions or typings.
import { InjectionToken } from '#angular/core';
export const JQ_TOKEN = new InjectionToken('jQuery');
export function jQueryFactory() {
return window['jQuery'];
}
export const JQUERY_PROVIDER = [
{ provide: JQ_TOKEN, useFactory: jQueryFactory },
];
When set correctly in your app.module.ts:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { JQ_TOKEN } from './jQuery.service';
declare let jQuery: Object;
#NgModule({
imports: [
BrowserModule
],
declarations: [
AppComponent
],
providers: [
{ provide: JQ_TOKEN, useValue: jQuery }
],
bootstrap: [AppComponent]
})
export class AppModule { }
You can start using it in your components:
import { Component, Inject } from '#angular/core';
import { JQ_TOKEN } from './jQuery.service';
#Component({
selector: "selector",
templateUrl: 'somefile.html'
})
export class SomeComponent {
constructor( #Inject(JQ_TOKEN) private $: any) { }
somefunction() {
this.$('...').doSomething();
}
}
After Angular's Final Release, (for jquery.js and bootstrap.js)
1) add following npm packages
npm install --save-dev #types/jquery
npm install --save-dev #types/bootstrap
2) in tsconfig.json add following entries in types array,
"types": [
"jquery",
"bootstrap",
]
And now you are good to go now.
Jquery carousel method error in Angular2/typescript

Typescript - internal module cannot be imported - unexpected behavior

I have 2 modules spread across 2 files as such:
--App.Tools.Utils.ts
export interface ILogger {
log: (msg: string) => void;
}
module App.Tools.Utils {
export class Logger implements ILogger { ... }
export function someFunction(){ ... }
}
then in the second file I import the module:
--App.Routers.ts
/// <reference path="App.Tools.Utils.ts" />
module App.Routers {
import Utils = App.Tools.Utils; //ERROR: A module cannot be aliased to a non-module type
}
I eventually figured out the solution was to move the ILogger interface INSIDE the App.Tools.Utils module to resolve the error. At first it made some sense, I figured the compiler wouldn't let me import the module because the Logger class implemented an interface that was not included in the module. To test, I moved the ILogger interface inside the module (error resolved) but then added an arbitrary interface right outside the module (one that is not used inside the module or anywhere) and the error returns..
export interface INeverUsed { } //generates same error
module App.Tools.Utils {
export interface ILogger {
log: (msg: string) => void;
}
export class Logger implements ILogger { ... }
export function someFunction(){ ... }
}
Looking at the generated JS, adding the interface outside the module generates a define(["require", "exports"] wrapper and that results in the error when trying to import the App.Tools.Utils module in the other file. Removing the interface removes the define wrapper and the resolves the error.
Is it behavior expected? It makes no sense to me why a module is suddenly "closed" when I define an interface in the same file but outside the module, especially if that interface is not even used inside the module.
Because you are using the export keyword on the interface, the compiler is treating the file as a module.
If you remove the export keyword on the interface, it should work:
interface ILogger {
log: (msg: string) => void;
}
module App.Tools.Utils {
export class Logger implements ILogger {
log(msg: string) { }
}
export function someFunction(){ }
}
And
///<reference path="game.ts" />
module App.Routers {
import Utils = App.Tools.Utils; // works
}

Categories

Resources