-1

Is there a way to create type in typescript with methods that when I call these methods, they have access to the variable's value? Equals what the array, for example, which has the method find.

Example:

const arrayVar: Array = [1,2,3];

array.find(el => el === 1); 

In this case, find has access to the value of the array arrayVar without me having to pass it via a parameter to a function, for example, I wanted to create something in this way, for example:

const myVar: MyCustomType = 5;

myVar.add(2); // Nesse caso, o retorno seria 7. 

I know it can be done with classes and functions, but then I would have to pass the value of "myVar" as a parameter (function add (value1, value2), for example), I wanted a way to access it directly, just like the type Array does in its methods.

  • 1
    Have you looked into how `this` works in JavaScript? – Pointy Sep 05 '22 at 14:46
  • 1
    "I know it can be done with classes and functions, but then I would have to pass the value of "myVar" as a parameter" - **that's not true**. Inside a method you have access to `this` which is the object (`myVar`) itself. – mikemaccana Sep 05 '22 at 15:01

3 Answers3

1

To make a subclass of Number with new methods:

class SwagNumber extends Number {
  add(number: number) {
    // Tell the TS compiler that `this` is an unboxed Number
    return (this as unknown as number) + number;
  }
}

Then to use:

const six = new SwagNumber(6);

six will be typed to SwagNumber by the TS compiler.

And to show it works:

six.add(5)
> 11

Let's look at the Constructor used, part of the Class:

> six.constructor
[class SwagNumber extends Number]

This will also leave the original Number prototype unchanged, which will stop any potential issues (double dots are used to use a method on a number, to distinguish the dot from a decimal point!)

> 3..constructor
[Function: Number]

or:

> (3).constructor
[Function: Number]

See Classes on MDN

However there's some danger here

Since SwagNumber is an object, and a regular number isn't an object by default (until you call its methods), comparisons won't work properly:

> six === 6
false

See Why should you not use Number as a constructor?

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
  • I 100% agree this is better than poluting the `Number` interface. its a shame TS doesnt define a way to make `const six: SwagNumber = 6` work. – Jamiec Sep 05 '22 at 15:33
  • @Jamiec It does - `const myNum = new SwagNumber(6)` – mikemaccana Sep 05 '22 at 15:34
  • I mean without the `new` keyword as when you define a native Number. Something like c# implict cast between number and `SwagNumber` – Jamiec Sep 05 '22 at 15:35
  • @Jamiec I see - remember TS is no longer there at runtime (unlike C#) so JS needs a way to know `myNum` is `SwagNumber` – mikemaccana Sep 05 '22 at 15:43
0

You could do this by adding your add method to a prototype:

interface Number {
    add: (val:number) => number;
}

Number.prototype.add = function(val:number): number{ 
    
  return (this as number) + val;
}

var myVal: Number = 5
console.log(myVal.add(7))

TS Playground Link

Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • Keep in mind there's already a type called `Number`, which is used for all numbers (except `BigInt`s) , in JS/TS - maybe use a different name? – mikemaccana Sep 05 '22 at 15:03
  • @mikemaccana that was my first thought too, but if you want to extend a `Number` to add an `add` method it needs to be called `Number` - unless im missing something in TS, which is entirely possible! – Jamiec Sep 05 '22 at 15:06
  • thansk for being polite! yes it's possible you just need to subclass. I didn't want to add an answer (to me this seems like the question asker got some bad information about `this`) but I've added one with a subclass of Number. – mikemaccana Sep 05 '22 at 15:27
0

If you want to invoke functions on an object at this point create a dedicated class. Why? Because you have structured zone where you can add/remove/edit and reuse in other part of code.

Sorry, i write in JS but you can change with no effort in TypeScript

Create Class Element

class CustomArray {

    constructor() {
        this.arr = [];
    }

    add(value) {
        this.arr.push(value)
    }

    erase(){
        this.arr = [];
    }

    // so on...

    print(){
        console.log(this.arr)
    }

}

//I use Module, so i will use require.
module.exports = CustomArray;

The above class is simplest example. You can decorate with other functions. In theory as many as you want

FOR USE INSIDE OTHER CONTEXT

const CustomArray = require("./CustomArray");

var arr = new CustomArray();
arr.add(2)
arr.print()