简体   繁体   English

打字稿用函数创建自己的类型

[英]Typescript creating own types with functions

I'm trying to create my own types on which i can call functions using the dot syntax .我正在尝试创建我自己的类型,我可以使用dot syntax在其上调用函数。

for example:例如:

let myOwnType: myByteType = 123211345;
myOwnType.toHumanReadable(2);

I want to archive the same behavior like number, array etc. I don't want to create my type using the call signature or constructor signature我想存档相同的行为,如数字、数组等。我不想使用调用签名或构造函数签名创建我的类型

So after looking into the typescript libary i saw this number interface:因此,在查看打字稿库后,我看到了这个数字界面:

interface Number {
    /**
     * Returns a string representation of an object.
     * @param radix Specifies a radix for converting numeric values to strings. This value is only used for numbers.
     */
    toString(radix?: number): string;

    /**
     * Returns a string representing a number in fixed-point notation.
     * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
     */
    toFixed(fractionDigits?: number): string;

    /**
     * Returns a string containing a number represented in exponential notation.
     * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
     */
    toExponential(fractionDigits?: number): string;

    /**
     * Returns a string containing a number represented either in exponential or fixed-point notation with a specified number of digits.
     * @param precision Number of significant digits. Must be in the range 1 - 21, inclusive.
     */
    toPrecision(precision?: number): string;

    /** Returns the primitive value of the specified object. */
    valueOf(): number;
}

The Problem is that i could not find where and how the function bodys gets defined.问题是我找不到函数体的定义位置和方式。 I was thinking there must be a class implementing the interface or something like this.我在想必须有一个类实现接口或类似的东西。

I came up trying something like this:我想出来尝试这样的事情:

interface Bytes {
  toHumanReadable(decimals: number): bytesToHumanReadable;
  bytesAs(unit: string): string;
}


function bytesToHumanReadable (decimals: number) {
  // convert bytes to GB, TB etc..
}

How could i create my own types and use them just like a normal type?我如何创建自己的类型并像普通类型一样使用它们? I know that the Interface doesn't work either but it was my first guess.我知道接口也不起作用,但这是我的第一个猜测。

The Problem is that i could not find where and how the function bodys gets defined.问题是我找不到函数体的定义位置和方式。

They're defined by the JavaScript engine, as part of the standard library.它们由 JavaScript 引擎定义,作为标准库的一部分。 You'll find them on Number.prototype .你会在Number.prototype上找到它们。 Here's how it works: When you try to access a property on a primitive (for instance, someNumber.toString() ), the JavaScript engine looks for the property on the prototype of that primitive's object type (number => Number , string => String , etc.).它的工作原理如下:当您尝试访问基元(例如someNumber.toString() )上的属性时,JavaScript 引擎会在该基元的对象类型(number => Number , string => String等)。 If you're making a call, it calls the method, passing in either the primitive (in strict mode) or an object wrapper for the primitive (in loose mode).如果您进行调用,它会调用该方法,传入原语(在严格模式下)或原语的对象包装器(在松散模式下)。

You can't define your own primitive type, that can only be done at the JavaScript specification level.您无法定义自己的原始类型,只能在 JavaScript 规范级别完成。

You could create a Byte class and have instances of it, but they'd be objects, not primitives.您可以创建一个Byte类并拥有它的实例,但它们是对象,而不是基元。

class Byte {
    constructor(public value: number) {
    }
    yourMethodHere() {
        // ...
    }
}

You can also add methods to Number.prototype , although it's best not to do that in any library code you may share with others.您还可以向Number.prototype添加方法,但最好不要在您可能与他人共享的任何库代码中这样做。 (Within your own app or page it's mostly fine, just be sure to use names that are unlikely to be used by future features of the standard library.) (在您自己的应用程序或页面中,大多数情况下都可以,只需确保使用标准库未来功能不太可能使用的名称即可。)

For instance, this adds a toHex method to numbers:例如,这向数字添加了一个toHex方法:

// Adding it to the type
interface Number {
    toHex(): string;
}
// Adding the implementation
Object.defineProperty(Number.prototype, "toHex", {
    value() {
        return this.toString(16);
    },
    enumerable: false, // This is the default, but just for emphasis...
    writable: true,
    configurable: true
});

Live example on the playground 操场上的活生生的例子

TJ Crowder great answer i expanded a bit on it TJ Crowder 很好的答案,我对此进行了扩展

 interface myByteType extends Number {
      toHumanReadable?(): string;
     }

    // Adding the implementation
    Object.defineProperty(Number.prototype, "toHumanReadable", {
      value() {
          return this.toString(16);
      },
      enumerable: false, // This is the default, but just for emphasis...
      writable: true,
      configurable: true
    });

    let a: myByteType = 2124;
    a.toHumanReadable();

with the questionmark syntax you have a workaround to use your own type with your defined function !使用问号语法,您有一种解决方法可以将您自己的类型与您定义的函数一起使用!

You're already halfway there with the bytesToHumanReadable function but you're missing one key thing.您已经完成了bytesToHumanReadable函数的一半,但您错过了一件关键的事情。

Since you want to add new functionality to numbers, you'll have to extend the base NumberConstructor interface and implement the functionality yourself.由于您想为数字添加新功能,您必须扩展基本NumberConstructor接口并自己实现该功能。 Let's take a look at this in practice.让我们在实践中看看这个。

interface myByteType extends NumberConstructor = {
 toHumanReadable: (decimals: number): string
}

This is simply to satisfy the TypeScript compiler.这只是为了满足 TypeScript 编译器。 You still have to implement the functionality yourself by extending the Number prototype like so:您仍然需要通过扩展Number原型来自己实现功能,如下所示:

Number.prototype.toHumanReadable = function(decimals: number) {
 // convert bytes to GB, TB etc.. 
}

You can then use the toHumanReadable function on any variable that extends the myByteType interface like so:然后,您可以对任何扩展myByteType接口的变量使用toHumanReadable函数,如下所示:

const secondsSinceOpened: myOwnType = 1334244200

secondsSinceOpened.toHumanReadable(2)

This question is very similar to this one so you could check it for further reading.这个问题是非常相似, 这一个,所以你可以检查它进一步阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM