typescript - Typescript 根据是否存在变量更改返回值的类型推断
问题描述
我对以下代码感到困惑:
type TestSymbol = 'a' | 'b';
type TestType = { test: TestSymbol }
function test1(): TestType { // no error
return { test: 'a' };
}
function test2(): TestType { // tsserver error 2322
const x = { test: 'a' };
return x;
}
错误信息是:
Type '{ test: string; }' is not assignable to type 'TestType'.
Types of property 'test' are incompatible.
Type 'string' is not assignable to type 'TestSymbol'.
[tsserver: 2322]
看来打字稿在 和 中对返回对象的属性test
进行了不同的分类。在中,它知道该值为 a 。但在 中,它只将其归类为字符串,导致类型错误。test1
test2
test1
'a'
TestSymbol
test2
为什么它会这样做,我如何帮助 typescript 理解它test
是TestSymbol
in test2
?
解决方案
当变量或其他表达式上没有显式类型注释时,TypeScript 编译器将根据一些启发式规则推断其类型,这些规则是对预期类型的合理猜测。这些规则并不完美,但它们很有用。
在你的第一个例子中,
function test1(): TestType {
return { test: 'a' };
}
编译器通过函数的返回类型{test: 'a'}
来推断要在TestType
上下文中使用的类型。上下文类型推断意味着编译器根据预期的类型推断表达式的类型。这仅在特定情况下发生,并且如果已经为值推断出类型,则不会发生。
例如,当您声明如下变量时:
const x = { test: 'a' };
x
编译器会立即根据 value推断出 的类型{test: 'a'}
。它不会等到它x
在某处看到使用时才知道最好的类型是什么。推断的类型是{test: string}
。即使x
是 a const
,该属性x.test
也可以更改,因此编译器假定它x.test
可以是 any string
。通常这样的假设是正确的,但在你的情况下它不是。
要解决此问题,您可以显式注释 的类型x
:
function testAnnotation(): TestType {
const x: TestType = { test: 'a' }; // <-- explicit annotation
return x; // okay
}
或者您可以使用const
断言来更改推理启发式,以便编译器假定任何内容x
都不会改变:
function testConstAssertion(): TestType {
const x = { test: 'a' } as const; // <-- ask for narrowest possible type
// const x: { readonly test: "a"; }
return x; // okay
}
现在的推断类型x
是{ readonly test: "a"; }
; 编译器假定该test
属性永远不会改变,并且它唯一可能的值是"a"
. 这被视为可分配给(属性可分配给非属性TestType
的事实有点奇怪,但这是预期的行为,您可以在microsoft/TypeScript#13347阅读更改此设置的建议)并且没有编译器错误。readonly
readonly
无论哪种方式都应该有效。
请注意,我不建议使用以下形式的类型断言:
function testLessSafeTypeAssertion(): TestType {
const x = { test: 'a' } as TestType;
return x;
}
虽然这将编译,但它不太安全,因为您只是告诉编译器这{test: "a"}
是 aTestType
而不是要求编译器验证它。类型断言往往会遗漏某些错误:
const x = { test: Math.random() < 0.5 ? 'a' : 'z' } as TestType; // no error!
类型注释在哪里捕获它们:
const x: TestType = { test: Math.random() < 0.5 ? 'a' : 'z' }; // error
类型断言主要在编译器无法验证值的类型并且您需要向编译器提供它没有的信息的情况下很有用。在这种情况下,编译器可以自行检查是否x
为 a ,因此注释或断言更安全。TestType
const
推荐阅读
- r - 如何转换 KEGG 过度表示测试的热图的 X 轴以显示基因符号而不是基因 entrez ID?
- python - python 中 os.remove() 的源代码
- sql - libpq 的 PQexecPrepared 和 SQL EXECUTE 的正确行为
- python - 如何暗示变量是从另一个类继承的类?
- uitabbarcontroller - iPhone X 标签栏和导航栏问题
- java - 是否可以使用 Java 为各种元素定位器重载 Selenium 中的 click 方法
- java - 创建一个不能被 file.delete() 删除的文件
- c++ - 在野牛的堆栈变量中赋值
- python - 使用 ctypes 从 C 结构数组到 NumPy 数组的高效转换
- sql - 在不中断正在进行的插入的情况下扫描大表以删除记录的更好方法