简体   繁体   English

打字稿:如何定义可调用对象?

[英]Typescript: how to define an invokable object?

This comes from @types/d3: 这来自@ types / d3:

export interface ScaleContinuousNumeric<Range, Output> {
    (value: number | { valueOf(): number }): Output;

but that's an interface. 但这是一个接口。 How do I define a class, the instances of which can be invoked like functions? 如何定义一个类,可以像函数一样调用其实例? Something like this: 像这样:

const inverter = new Inverter();
const question = inverter(42);

Maybe there is some kind of special ES6 Symbol like 也许有某种特殊的ES6符号,例如

class Inverter {
    [Symbol.invokable]() {

    }
}

or TypeScript syntax? 或TypeScript语法?

You just define a regular function, that will satisfy the interface with the call signature: 您只需定义一个常规函数即可满足带有调用签名的接口:

export interface ScaleContinuousNumeric<Range, Output> {
    (value: number | { valueOf(): number }): Output;
}

let a : ScaleContinuousNumeric<number, string> = (value) => value.toString()

If the interface has other methods you can use Object.assign to create the function and add the properties: 如果接口具有其他方法,则可以使用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
    });

Or in typescript 3.0 you can create the function, assign the extra properties and then the function will be compatible with the interface: 或者在打字稿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

I had a similar problem. 我有一个类似的问题。 I needed to implement a custom scale in Typescript. 我需要在Typescript中实现自定义比例。 The following worked. 以下工作。

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;

};

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

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