打字稿:如何定义可调用对象?
Typescript: how to define an invokable object?
本文来自@types/d3:
export interface ScaleContinuousNumeric<Range, Output> {
(value: number | { valueOf(): number }): Output;
但那是一个界面。我如何定义一个 class,它的实例可以像函数一样被调用?像这样:
const inverter = new Inverter();
const question = inverter(42);
也许有某种特殊的 ES6 符号,例如
class Inverter {
[Symbol.invokable]() {
}
}
还是 TypeScript 语法?
您只需定义一个常规函数,它将满足具有调用签名的接口:
export interface ScaleContinuousNumeric<Range, Output> {
(value: number | { valueOf(): number }): Output;
}
let a : ScaleContinuousNumeric<number, string> = (value) => value.toString()
如果接口有其他方法可以使用Object.assign
创建函数并添加属性:
export interface ScaleContinuousNumeric<Range, Output> {
(value: number | { valueOf(): number }): Output;
otherValue: Range
}
let a: ScaleContinuousNumeric<number, string> = Object.assign(
(value: number | { valueOf(): number }) => value.toString(), {
otherValue: 1
});
或者在 typescript 3.0 中,您可以创建函数,分配额外的属性,然后函数将与接口兼容:
export interface ScaleContinuousNumeric<Range, Output> {
(value: number | { valueOf(): number }): Output;
otherValue: Range
}
function myFunc(value: number | { valueOf(): number }) {
return value.toString()
}
myFunc.otherValue = 1
let a: ScaleContinuousNumeric<number, string> = myFunc
我遇到了类似的问题。我需要在 Typescript 中实现自定义比例。以下工作。
let scaleLinear = function () {
// To translate from domain [a, b] to range [c, d] we use:
// y = x.m + n;
// where
// m = (c - d)/(a - b)
// n = (a.d - b.c)/(a - b)
//
let _range = [0, 1];
let _domain = [0, 1];
let _clamp = false;
let _m = 1.0;
let _n = 0.0;
function scale(value: number) {
return value * _m + _n;
}
scale.rescale = function () {
// Called internally to recalc scale values
_m = (_range[0] - _range[1]) / (_domain[0] - _domain[1]);
_n = (_domain[0] * _range[1] - _domain[1] * _range[0]) / (_domain[0] - _domain[1]);
}
scale.invert = function (value:number) {
return (value - _n) / _m;
}
scale.domain = function (domain?: any): any {
if (arguments.length) {
_domain = arguments[0].slice();
scale.rescale();
return scale;
}
return _domain;
}
scale.range = function (range?: any): any {
if (arguments.length) {
_range = arguments[0].slice();
scale.rescale();
return scale;
}
return _range;
}
// Statics
scale.nice = function () {
// do nothing
}
return scale;
};
本文来自@types/d3:
export interface ScaleContinuousNumeric<Range, Output> {
(value: number | { valueOf(): number }): Output;
但那是一个界面。我如何定义一个 class,它的实例可以像函数一样被调用?像这样:
const inverter = new Inverter();
const question = inverter(42);
也许有某种特殊的 ES6 符号,例如
class Inverter {
[Symbol.invokable]() {
}
}
还是 TypeScript 语法?
您只需定义一个常规函数,它将满足具有调用签名的接口:
export interface ScaleContinuousNumeric<Range, Output> {
(value: number | { valueOf(): number }): Output;
}
let a : ScaleContinuousNumeric<number, string> = (value) => value.toString()
如果接口有其他方法可以使用Object.assign
创建函数并添加属性:
export interface ScaleContinuousNumeric<Range, Output> {
(value: number | { valueOf(): number }): Output;
otherValue: Range
}
let a: ScaleContinuousNumeric<number, string> = Object.assign(
(value: number | { valueOf(): number }) => value.toString(), {
otherValue: 1
});
或者在 typescript 3.0 中,您可以创建函数,分配额外的属性,然后函数将与接口兼容:
export interface ScaleContinuousNumeric<Range, Output> {
(value: number | { valueOf(): number }): Output;
otherValue: Range
}
function myFunc(value: number | { valueOf(): number }) {
return value.toString()
}
myFunc.otherValue = 1
let a: ScaleContinuousNumeric<number, string> = myFunc
我遇到了类似的问题。我需要在 Typescript 中实现自定义比例。以下工作。
let scaleLinear = function () {
// To translate from domain [a, b] to range [c, d] we use:
// y = x.m + n;
// where
// m = (c - d)/(a - b)
// n = (a.d - b.c)/(a - b)
//
let _range = [0, 1];
let _domain = [0, 1];
let _clamp = false;
let _m = 1.0;
let _n = 0.0;
function scale(value: number) {
return value * _m + _n;
}
scale.rescale = function () {
// Called internally to recalc scale values
_m = (_range[0] - _range[1]) / (_domain[0] - _domain[1]);
_n = (_domain[0] * _range[1] - _domain[1] * _range[0]) / (_domain[0] - _domain[1]);
}
scale.invert = function (value:number) {
return (value - _n) / _m;
}
scale.domain = function (domain?: any): any {
if (arguments.length) {
_domain = arguments[0].slice();
scale.rescale();
return scale;
}
return _domain;
}
scale.range = function (range?: any): any {
if (arguments.length) {
_range = arguments[0].slice();
scale.rescale();
return scale;
}
return _range;
}
// Statics
scale.nice = function () {
// do nothing
}
return scale;
};