打字稿用函数创建自己的类型
Posted
技术标签:
【中文标题】打字稿用函数创建自己的类型【英文标题】:Typescript creating own types with functions 【发布时间】:2020-06-13 10:12:45 【问题描述】:我正在尝试创建自己的类型,我可以使用 dot syntax
在其上调用函数。
例如:
let myOwnType: myByteType = 123211345;
myOwnType.toHumanReadable(2);
我想归档相同的行为,例如数字、数组等。 我不想使用调用签名或构造函数签名来创建我的类型
所以在查看了 typescript 库后,我看到了这个数字界面:
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;
问题是我找不到函数体的定义位置和方式。我在想一定有一个实现接口的类或类似的东西。
我想出了这样的尝试:
interface Bytes
toHumanReadable(decimals: number): bytesToHumanReadable;
bytesAs(unit: string): string;
function bytesToHumanReadable (decimals: number)
// convert bytes to GB, TB etc..
我如何创建自己的类型并像使用普通类型一样使用它们? 我知道接口也不起作用,但这是我的第一个猜测。
【问题讨论】:
您可能想使用class
,而不是interface
(请参阅***.com/a/55505227/2358409)
【参考方案1】:
T.J.克劳德很好的答案,我对此进行了扩展
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();
使用问号语法,您有一个解决方法,可以将您自己的类型与您定义的函数一起使用!
【讨论】:
【参考方案2】:问题是我找不到函数体的定义位置和方式。
它们由 javascript 引擎定义,作为标准库的一部分。您可以在Number.prototype
上找到它们。它是这样工作的:当你尝试访问一个原始的属性(例如,someNumber.toString()
)时,JavaScript 引擎会在该原始对象类型的原型上查找属性(数字 => Number
,字符串 => String
等)。如果您正在进行调用,它会调用该方法,传入原语(在严格模式下)或原语的对象包装器(在松散模式下)。
您无法定义自己的原始类型,只能在 JavaScript 规范级别完成。
您可以创建一个Byte
类并拥有它的实例,但它们将是对象,而不是原语。
class Byte
constructor(public value: number)
yourMethodHere()
// ...
您也可以向Number.prototype
添加方法,但最好不要在您可能与他人共享的任何库代码中这样做。 (在您自己的应用程序或页面中,这几乎没有问题,只需确保使用标准库的未来功能不太可能使用的名称。)
例如,这会将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
【讨论】:
很好的解释。我真的不想在数字原型中添加一个方法,因为你已经提到了可能的麻烦。我将更多地了解 javascript 引擎本身,并可能使用接口和对象来代替。【参考方案3】:bytesToHumanReadable
函数已经完成了一半,但你缺少一件关键的事情。
由于您想为数字添加新功能,您必须扩展基本的NumberConstructor
接口并自己实现该功能。让我们在实践中看看这个。
interface myByteType extends NumberConstructor =
toHumanReadable: (decimals: number): string
这只是为了满足 TypeScript 编译器。您仍然必须通过像这样扩展 Number
原型来自己实现该功能:
Number.prototype.toHumanReadable = function(decimals: number)
// convert bytes to GB, TB etc..
然后您可以对任何扩展myByteType
接口的变量使用toHumanReadable
函数,如下所示:
const secondsSinceOpened: myOwnType = 1334244200
secondsSinceOpened.toHumanReadable(2)
这个问题与this one 非常相似,因此您可以查看它以进一步阅读。
【讨论】:
通过赋值在内置原型上创建属性并不是最佳实践。确保该属性是不可枚举的(请参阅我的答案了解如何)。 上面给出了const secondsSinceOpened: myOwnType = 1334244200
的类型错误(如果我用接口定义修复了各种错误并使类型名称匹配):“类型'1334244200'不可分配给类型' myOwnType'"(如果您尝试分配键入 number
的内容也会抱怨)。以上是关于打字稿用函数创建自己的类型的主要内容,如果未能解决你的问题,请参考以下文章