类型推断成功取决于命名值

时间:2016-11-05 21:11:35

标签: typescript typescript1.8

我还是TypeScript的新手,经常发现我觉得奇怪的事情。

拿这段代码:

interface MyInterface<T> {
    [i: string]: T;
}

function myFunc<T>(arg: MyInterface<T>) { }

var o = { 'val1': 42, 'val2': 43 };

myFunc(o);

电话会议失败,投诉“索引签名丢失”。

有趣的是,当我写

时,它并没有丢失
myFunc({ 'val1': 42, 'val2': 43 });

这意味着表达式{ 'val1': 42, 'val2': 43 }的类型是从调用向后推断的(这在某种程度上是预期的),但在绑定到名称时却不是这样(这很奇怪而不是我怎么知道后向推断到例如,来自F#的工作。

但它变得更加陌生。

如果我将界面更改为

interface MyInterface<T> {
    [i: number]: T;
}
然后是相应的

var o = [42, 43];

myFunc(o);

也有效(除了直接传递数组)。

这是设计吗?有什么规则可以解释这个?

1 个答案:

答案 0 :(得分:1)

您看到这种不一致的原因是因为您使用的是TypeScript 1.8。如果您在TypeScript游乐场中尝试wikipedia

在TS 1.8中出现这种情况的原因是因为当您将对象文字直接放在对arg的调用中时,它是由o 在上下文中键入的,其类型有一个索引签名。结果,推断类型获得了索引签名。

上下文输入不会修改变量的先前推断类型(声明的类型),因此当您尝试将myFunc传递给o时,会出现错误function httpService(path: string, headers: { [x: string]: string }) { } const headers = { "Content-Type": "application/x-www-form-urlencoded" }; httpService("", { "Content-Type": "application/x-www-form-urlencoded" }); // Ok httpService("", headers); // Now ok, previously wasn't 缺少索引签名。

在TypeScript 2.0(及以上版本)中,这些场景非常痛苦,我们引入了隐式索引签名的概念。在这里查看提取请求:you'll see either one works

引用:

  

使用此PR,如果对象文字中的所有已知属性都可分配给该索引签名,则对象文字类型可分配给具有索引签名的类型。这使得可以将使用对象文字初始化的变量作为参数传递给需要地图或字典的函数:

JavaInputDStream<byte[]> directKafkaStream = KafkaUtils.createDirectStream(jsc, String.class, byte[].class,
        StringDecoder.class, DefaultDecoder.class, byte[].class, kafkaParams, topicMap,
        (Function<MessageAndMetadata<String, byte[]>, byte[]>) MessageAndMetadata::message);

directKafkaStream.foreachRDD(rdd -> {
    rdd.foreachPartition(itr -> {
        Integer partnId = TaskContext.get().partitionId();

        ArrayList <byte[]> recordBatch = new ArrayList <byte[]>();

            while (itr.hasNext()) {
                byte[] record = itr.next();
                recordBatch.add(record);
            }

                OffsetRange[] offsets = ((HasOffsetRanges) rdd.rdd()).offsetRanges();
            //Partition 0 fromOffset 0 untilOffset 2 offset.count(): 2
            //Partition 1 fromOffset 0 untilOffset 3 offset.count(): 3
                for (OffsetRange offset : offsets) {

                    if (offset.partition() == partnId) {
                        recordBatch.forEach((rec) -> {
                        //Partition 0 fromOffset 0 untilOffset 2 offset.count(): 2 --> TOTAL RECORDS after LOOPING: 3
                        //Partition 1 fromOffset 0 untilOffset 3 offset.count(): 3 --> TOTAL RECORDS after LOOPING: 3
                            //Business Logic goes here.
                        }
                    } 
                } 

    });
});