可以使用typescript 1.4中的联合类型来声明d3-style" chained"的getter / setter方法?

时间:2015-02-21 04:11:03

标签: typescript

D3这样的库中的常见模式是“可堆叠的getter / setter”。

例如(来自this example):

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

此处,chargelinkDistancesize用作setter,每个setter都返回force对象的一个​​实例,以便它们可以“链接”。

但是,它们也可以通过不指定参数而用作吸气剂,例如:

var d = force.linkDistance()

如果在第一个代码块之后调用,则d的值现在为30

我想使用typescript 1.4的新联合类型功能来创建这样的可链接的getter / setter。例如,以下内容编译为正确的javascript:

class O {
    private _a: number = 0;
    a(x: number = null): O|number {
        if (x) {
            this._a = x;
            return this;
        }
        return this._a;
    }
}

这样从javascript我可以做到:

var o = new O();
var v = o.a(3).a();

现在v = 3.

但是从打字稿中,我需要施放:

var o = new O();
var v: number = <number>(<O>o.a(3)).a();

不太吸引人!

有趣的是,看看d3.d.ts,似乎人们一直在创建具有正确签名的接口,如下所示:

interface IA {
    a: {
        (): number;
        (x: number): IA;
    }
}

这在某种程度上神奇地解析为正确的签名来包装javascript,但我不知道如何在typescript中实现这样的接口!

所以我的问题是,是否可以编写这样的可链接的getter / setter而不需要在使用typescript中调用时使用强制转换?或者,是否可以创建实现接口IA

的typescript类

2 个答案:

答案 0 :(得分:4)

  

是否有可能对这些可链接的getter / setter进行编码而不需要在使用typescript中调用时使用强制转换?或者,是否可以创建实现接口IA

的typescript类

是。使用函数重载:

interface IA {
    a: {
        (): number;
        (x: number): IA;
    }
}

class A implements IA {
    private _a;
    a(): number
    a(x: number): A
    a(x?: any): any {
        if (x == void 0){
            return this._a;
        }
        else {
            this._a = x;
            return this;
        }
    }
}

var foo = new A(); 
var bar = foo.a(123); // okay
console.log(bar.a()); // 123
foo.a('not a number'); // Error 

答案 1 :(得分:1)

返回你实际创建新类型O|number

的联合类型
var o2: O|number = o.a(3);

TypeScript编译器无法在不进行强制转换的情况下理解您需要的确切类型。

实际上,引入的联合类型主要是为了删除函数重载,并且只能使用类型转换/检查来使用它们(至少现在)。

对于您的示例,我能看到的唯一方法是使用2种不同的方法来设置和获取值:

class O {
    private _a: number = 0;

    setA(x: number): O {        
        this._a = x;
        return this;
    }

    getA(): number {
        return this._a; 
    }
}

var o: O = new O();
var v: number = o.setA(3).getA();