Hans Bäuml
Hans Bäuml

Reputation: 229

Is it possible to have getters and setters in typescript declaration file?

I have a problem with a declaration file. I try to write d.ts files for the openUi framework. They use a get<propname>() and set<propname>(var) syntax for their properties.

In JS I would have the following Setup:

sap.ui.getCore().attachInit(function () {
    var text = new sap.m.Text();
    text.setText("Hello World!"); // sets the text property
    text.placeAt("content", 0);
});

In Typescript I would like to have the getter and setter Syntax like this:

var textcontrol = new sap.m.Text();
var textcontrol.Text = "Hello World"; // Sets the text property in typescript.
var text = textControl.Text; // Gets the text in typescript.

which should compile to this in my JS output:

var textcontrol = new sap.m.Text();
var textcontrol.setText("Hello World"); // Sets the text property in typescript.
var text = textControl.getText(); // Gets the text in javascript.

When trying to declare the method in my declaration file I get the error that it is not allowed to declare setters or getters in an ambient environment. Therefore, I guess this does not work as I liked to (or maybe it does and I am not doing it right).

In a normal typescript file I can use getters and setters

get Text(): string { return _text; };
set Text(value: string { _text = value };

but in a d.ts file I cannot.

Is it somehow possible to declare that behavior in a d.ts file?

I can think of 2 options:

  1. Somehow making an internal module out of my definitions and wrap all the classes to match the syntax in js
  2. Making no d.ts files, but normal ts files which implement dummy return values and just will compile to the desired code.

Help would be much appreciated.

EDIT: A concrete Example:

I have for Example this JavaScript "class" to do a type definition for:

function Text() {}

Text.prototype.getText = function () {
    return this.Text;
}

Text.prototype.setText = function (value) {
    this.Text = value;
}

So the usage in JavaScript is:

var testtext = new Text();
testtext.setText("Hello World");
alert(testtext.getText())
// alerts Hello World

I would like to make a declaration file for that and use it in Typescript as follows:

var testtext = new Text();
testtext.Text = "Hello World";
alert(testtext.Text);

Is this possible after all?

Upvotes: 2

Views: 10140

Answers (2)

Fenton
Fenton

Reputation: 250942

If you have a property with a getter and setter, the declaration is as simple as:

declare class Test {
    Text: string;
}

var x: Test;

x.Text = 'hello world';

The syntax within a type definition is the same as for an interface, so Text: string is all you need.

Futures

If you need to have a getter or setter only, that feature is incoming - either as the readonly keyword which is in TypeScript 2.0

declare class Test {
    readonly Text: string;
}

...or with the ability to use get and set keywords in interfaces.

declare class Test {
    get Text(): string;
}

Methods

You can also describe methods that get an set backing properties. They are no different from normal methods:

declare class Test {
    setText(v: string): void;
    getText(): string;
}

Upvotes: 2

Hans B&#228;uml
Hans B&#228;uml

Reputation: 229

Answer from Typescript contributors:

https://github.com/Microsoft/TypeScript/issues/10969#issuecomment-248192537

It is not possible!

declares in d.ts files do not generate any code, therefore, you cannot replace anything by writing declares (obviously).

The only way is to extend the js classes with property declarations like this:

var Text = ...<initializing code>...;

Object.defineProperty(Text.prototype, "Text", {
   get: function () { return this.getText(); },
   set: function (value) { this.setText(value); },
   enumerable: true,
   configurable: true
   });

(For noobs like me: You do not have to do this in the constructor method.)

In the get and set function just call the getter and setter methods. This will not affect the JS code (at least not mine), hence, affect your transpiled js performance, if it is called too often.

Thank you, Sohnee, for your help.

Upvotes: 1

Related Questions