“type '{}'”是什么?

25
在TypeScript中,type '{}' 是什么,它与其他内置类型有何关系?
例如,以下示例的最后一行会显示Type '{}' is not assignable to type 'number',而我并不完全清楚在这种情况下type {}是什么,或者它是如何出现的。
// A function taking no arguments and returning T
type NoArgsFn<T> = () => T;

// An instance of NoArgsFn<number>
function get_the_answer(): number {
  return 42;
}

// Call the supplied function and return its value
function call<T, Fn extends NoArgsFn<T>>(fn: Fn): T {
  return fn();
}

// Expect this to be equivalent to `let the_answer: number = 42', but
// instead get "Type '{}' is not assignable to type 'number'"
let the_answer: number = call(get_the_answer);

1
一个好问题,因为在示例中不清楚{}是如何产生的。然而,我认为您不需要Fn泛型类型,这可能与T未解析为number有关。 - E net4
2
没错,谢谢。如果我去掉 Fn,错误就消失了。话虽如此,我仍然想了解 type {} 是什么以及为什么会出现在这里。 - NPE
这个回答解决了你的问题吗?TypeScript中的{}是什么意思? - Bart Louwers
4个回答

13

type {}

考虑表示具有2个字段的对象类型{ id: number, name: string }。此类型的合法值包括{ id: 1, name: "Foo" }{ id: 2, name: "Bar" }

类型对象{}表示一个0个字段的对象。该类型的唯一合法值是一个空对象:{}

因此,{ id: 1, name: "Foo" }类型{ id: number, name: string },而{}(即空对象)的类型{}

错误

这个错误似乎是TypeScript编译器中的一个bug(我在这里提交了一个问题here)。它未能推断调用call中的类型参数。你可以通过显式指定类型参数来解决这个问题:

let the_answer: number = call<number, NoArgsFn<number>>(get_the_answer);

但是,像@NitzanTomer建议的那样,使用单个类型参数更加简单和直接:

function call<T>(fn: NoArgsFn<T>): T {
  return fn();
}

编辑:我提交的问题被关闭为#7234的重复,这个问题将在TypeScript 2.0发布之前得到解决。


我认为值得注意的是,编译器推断 {} 类型不一定是它自己的错误。考虑 f<a>(one: a, two: a) 使用 f({foo: 2}, {bar: 'thing'}) 调用 -- 推测结果会是 {foo:number}|{bar:string}, 其中是 {} (没有任何共同点)。 - KRyan
3
我对这个答案进行了负评,因为它是错误的:const test: {} = true; 这是类型不正确的。 - Bart Louwers
2
Dan Vanderkam的书《Effective TypeScript》中提到:“{}类型包括除了nullundefined之外的所有值。”如果我按照Bart Louwer的评论编写代码,eslint会提示:“不要将{}用作类型。{}实际上意味着“任何非空值”。” - David Hull

5
您需要像这样拥有您的呼叫函数: ```html

您需要像这样拥有您的呼叫函数:

```
function call<T>(fn: NoArgsFn<T>): T {
    return fn();
}

在您原来的call函数中,您有两个通用类型,但在调用函数时没有传递,编译器无法推断它们的类型。


编辑

类型{}是一个对象文字(据我所知),因此您可能会遇到同样的错误:

var o = {};
var n: number = o; // Error: Type '{}' is not assignable to type 'number'

我不确定编译器为什么会推断出在你的例子中该函数返回{}


谢谢,但type '{}'到底是什么?(我也想了解为什么推断失败,但我们可以分开处理。) - NPE
@NPE,请检查我的修订答案。 - Nitzan Tomer
2
我一直在尝试以某种方式阅读规范,以证明这种行为的合理性,但是类型推断部分有点晦涩难懂。 - E net4

5
据我所知,{} 可以直接转换为类似使用哈希映射的方式。您只能使用键入属性,而不是点表示法。
var o:{} = {}

应该等同于

var o:{[key:string]:any} = {}

所以
o.x = 5; //fails

但是

o['x'] = 5; //succeeds

听起来很有趣。你有关于你的回答的任何参考资料吗? - Peter Lehnhardt

0
{} 是一种类型,可以被赋予除了 nullundefined(即非空值)之外的任何值。
它并不表示没有属性的对象字面量。如果你想要表示这样的对象,请使用类似 Record<PropertyKey, never> 的方式。
let value: {};

value = 5;
value = "Hello World";
value = ["banana", "apple", "orange"];
value = () => true;

value = null;
//~~~ Type 'null' is not assignable to type '{}'.
value = undefined;
//~~~ Type 'undefined' is not assignable to type '{}'.

TypeScript Playgrond


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接