1

I'm using a project mixed with both javascript and typescript. Declaration files for modules can be easily created using - declare module. But how do I create a declaration for a javascript file in my current folder?

For ex -

player.js -
var Player = function() {};
Player.prototype.validate = function() {};

How do I create declaration so that I can extend it in typescript. I want to do something like this -

player.ts -
let Player = require('./player');
Player.prototype.login = function() {
    this.validate();
}

I know the above code will work by setting Player type as any but I won't be able to type check.

Nishant
  • 129
  • 1
  • 10

3 Answers3

1

TypeScript does not understand the prototypal syntax / constructor functions: there will be no intellisense. It prefers ES6 classes.

The JavaScript Player constructor function is equivalent to this TypeScript class definition:

// -- player.d.ts --
declare class Player {
  validate(): void;
}

Then, to add a method to the Player class, there's a couple of options:

  1. The more TypeScript idiomatic ways: class inheritance or class composition
  2. A compromise to keep using the prototypal syntax in TypeScript and still get the intellisense: facade interface

Code examples:

// -- authenticated-player.ts --
import { Player } from './player'; 

// Option #1a: class inheritance
class AuthenticablePlayer extends Player {
  login() {
    this.validate();
  }
}

const p1a = new AuthenticablePlayer();
p1a.login();

// Option #1b: class composition + delegation
class AuthenticablePlayerB {
  private player = new Player(); 

  login() {
    this.validate();
  }

  validate() {
    this.player.validate();
  }
}

const p1b = new AuthenticablePlayerB();
p1b.login();

--

// Option #2: prototype extension + facade interface + type assertion
const Player: any = require('./player');

Player.prototype.login = function() {
  this.validate();
}

interface IPlayer {
  login(): void;
  validate(): void;
}

function createPlayer(): IPlayer {
  return new Player();
}

const p2 = createPlayer();
p2.login();
Romain Deneau
  • 2,841
  • 12
  • 24
  • For more details on the difference between `declare class` and `interface`, see http://stackoverflow.com/a/14348084/1704166 – Romain Deneau Oct 01 '17 at 08:12
  • was hoping there was a way to add to current class without extending it. But I guess I'll have to extend. – Nishant Oct 02 '17 at 14:20
0

You can create interface in your TypeScript file and set that as the type for Player.

interface IPlayer {
  validate();
}

let Player: IPlayer = require('./player');

Player.prototype.login = function() {
    this.validate();
}
Sabbir Rahman
  • 1,191
  • 2
  • 13
  • 17
0

To expand on Sabbir's answer here (not enough room in comments)

interface IPlayer { 
  validate(): void
  login():void
}

old js code

var Player = function () { }
Player.prototype.validate = function() {}

using in ts project

// import / require here, left out for brevity
Player.prototype.login = function() {
    this.validate()
}

create a player - login and validate now have auto completion

let p: IPlayer = new Player()
p.login()
p.validate()
Kokodoko
  • 26,167
  • 33
  • 120
  • 197
  • but auto completion won't work inside the player function – Nishant Sep 30 '17 at 10:57
  • I don't know your exact project use case but personally I would prefer to create a Typescript Class and copy the JS methods over. Then you will get full code completion. Check the edit – Kokodoko Sep 30 '17 at 12:00
  • It's a really big class and I don't want to mix javascript and typescript code. – Nishant Oct 02 '17 at 14:21