类型推断的成功取决于命名一个值
Type inference success depends on naming a value
我对 TypeScript 还是个新手,经常发现我觉得很奇怪的东西。
取此代码:
interface MyInterface<T> {
[i: string]: T;
}
function myFunc<T>(arg: MyInterface<T>) { }
var o = { 'val1': 42, 'val2': 43 };
myFunc(o);
呼叫失败,投诉 "Index signature is missing"。
有趣的是,我写的时候没有漏掉
myFunc({ 'val1': 42, 'val2': 43 });
这意味着表达式 { 'val1': 42, 'val2': 43 }
的类型是从调用中向后推断的(这在某种程度上是预期的),但当绑定到一个名称时则不是这样(这很奇怪而且我不知道向后例如,从 F# 推断工作)。
但它变得更加陌生。
如果我将界面更改为
interface MyInterface<T> {
[i: number]: T;
}
然后对应的
var o = [42, 43];
myFunc(o);
也有效(除了直接传递数组)。
这是设计使然吗?解释这个的规则是什么?
您看到这种不一致的原因是因为您使用的是 TypeScript 1.8。如果您在 TypeScript playground 中尝试其中任何一个,you'll see either one works.
在 TS 1.8 中出现这种行为的原因是,当您将对象文字直接放在对 myFunc
的调用中时, [=12] 对其进行了上下文类型化=],其类型具有索引签名。结果,推断类型获得了索引签名。
上下文类型不会修改变量的先前推断类型(声明的类型),因此当您尝试将 o
传递给 myFunc
时,您收到 o
缺少索引签名的错误。
在 TypeScript 2.0(及更高版本)中,这些场景非常痛苦,因此我们引入了隐式索引签名 的概念。在此处查看拉取请求:https://github.com/Microsoft/TypeScript/pull/7029.
引用:
With this PR an object literal type is assignable to a type with an index signature if all known properties in the object literal are assignable to that index signature. This makes it possible to pass a variable that was initialized with an object literal as parameter to a function that expects a map or dictionary:
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 还是个新手,经常发现我觉得很奇怪的东西。
取此代码:
interface MyInterface<T> {
[i: string]: T;
}
function myFunc<T>(arg: MyInterface<T>) { }
var o = { 'val1': 42, 'val2': 43 };
myFunc(o);
呼叫失败,投诉 "Index signature is missing"。
有趣的是,我写的时候没有漏掉
myFunc({ 'val1': 42, 'val2': 43 });
这意味着表达式 { 'val1': 42, 'val2': 43 }
的类型是从调用中向后推断的(这在某种程度上是预期的),但当绑定到一个名称时则不是这样(这很奇怪而且我不知道向后例如,从 F# 推断工作)。
但它变得更加陌生。
如果我将界面更改为
interface MyInterface<T> {
[i: number]: T;
}
然后对应的
var o = [42, 43];
myFunc(o);
也有效(除了直接传递数组)。
这是设计使然吗?解释这个的规则是什么?
您看到这种不一致的原因是因为您使用的是 TypeScript 1.8。如果您在 TypeScript playground 中尝试其中任何一个,you'll see either one works.
在 TS 1.8 中出现这种行为的原因是,当您将对象文字直接放在对 myFunc
的调用中时, [=12] 对其进行了上下文类型化=],其类型具有索引签名。结果,推断类型获得了索引签名。
上下文类型不会修改变量的先前推断类型(声明的类型),因此当您尝试将 o
传递给 myFunc
时,您收到 o
缺少索引签名的错误。
在 TypeScript 2.0(及更高版本)中,这些场景非常痛苦,因此我们引入了隐式索引签名 的概念。在此处查看拉取请求:https://github.com/Microsoft/TypeScript/pull/7029.
引用:
With this PR an object literal type is assignable to a type with an index signature if all known properties in the object literal are assignable to that index signature. This makes it possible to pass a variable that was initialized with an object literal as parameter to a function that expects a map or dictionary:
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