Using external JS-Library (basic primitives diagrams) in Typescript

Viewed 130

I'm taking the first steps to migrate a rather large project from javascript to typescript. Beeing a Java developer who started javascript development just about 2 years ago, my toolchain is still rudimentary.

I'm trying to migrate a small JS file to TS as a proof of concept. The JS code configures a Basic Primitives Diagram.

Almost everything did work out. But I'm having big issues declaring the global scoped functions in a way typescript can understand. Here is a small portion of my code:

export {}
declare global {
  export interface Window {
    MyGlobalVar: any;
  }

  export ChartItemConfig{
    //properties
  }

  //I thought this and the following declarations would solve the problem. They dont :(
  export interface primitives {
    orgdiagram: Orgdiagram;
  }

  export interface Orgdiagram {
    Config: Config;
  }

  export interface Config {
    //properties
  }
}

window.MyGlobalVar.myGlobalFunction = function (id: string, items: Array<ChartItemConfig>) {
    //... more code
    // @ts-ignore
    let options: Config = new primitives.orgdiagram.Config();
    //... more code
 }

I want to get rid of the @ts-ignore Statement. But whatever I try, my code wont transpile. I get the error TS2693: 'primitives' only refers to a type, but is being used as a value here.

I'm sure it's a beginners problem, but I can't find the solution in the www.

Edit:

It seems i was not clear enough about my problem: new primitives.orgdiagram.Config(); is valid JS-Code at runtime. How can I declare the symbol in a way TS will understand it is a constructor call?

Edit:

Mycurrent version:

export {}
declare global {
  export interface Window {
    MyGlobalVar: any;
  }

  export const primitives:Primitives;

  export class Primitives {
    orgdiagram: Orgdiagram;
  }

  export class Orgdiagram {
    Config: () => Config;
  }

  export class Config { }
  
  //... more
}

window.MyGlobalVar.myGlobalFunction  = function (id: string, items: Array<ChartItemConfig>) {
  //The following line fails with: TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type
  let options: Config = new primitives.orgdiagram.Config();
  //... more
}

Edit:

I finally got it to work. The fettblog.eu introduced me to the constructor interface pattern, which solved my Problem :)

My working declaration is now

export {}
declare global {
      
  const primitives:Primitives;

  class Primitives {
    orgdiagram: Orgdiagram;
  }

  class Orgdiagram {
    Config: ConfigConstructor;
  }

  interface ConfigConstructor{
    new (): Config;
  }

  class Config {
    //....
1 Answers

What you need to do is declare a const:

declare global {
    export const primitives: Primitives

    export interface Primitives {
        orgdiagram: Orgdiagram;
    }
}

In this way you are telling Typescript "trust me, there is a constant declared somewhere else in the global scope that is called primitives and whose type is Primitives". And it generates the correct code.

As for the constructor, you need to specify that the function is a constructor in order to be able to use it with new:

export class Orgdiagram {
    Config: { new(): Config };
}
Related