简体   繁体   English

字符串文字的 TypeScript 推断

[英]TypeScript inference of string literals

My question is pretty simple.我的问题很简单。 Given this code:鉴于此代码:

const array = [1, 2, 3, 4, 5];
const map01 = array.map((v) => v % 2 ? "" : "");
//    ^? string[]
const map02 = array.map((v) => v % 2 ? "odd" : "even");
//    ^? ("odd" | "even")[]
const map03 = array.map((v) => v % 2 ? "!" : "");
//    ^? ("" | "!")[]

Why such odd inference by TypeScript?为什么 TypeScript 会做出如此奇怪的推断? Shouldn't map01 be inferred as ""[] ? map01不应该被推断为""[]吗?

Playground操场

在此处输入图像描述

The details for how and when literal type widening happens are laid out in microsoft/TypeScript#10676 . microsoft/TypeScript#10676中列出了文字类型扩展如何以及何时发生的详细信息。 In particular, it says:特别是,它说:

  • In a function with no return type annotation, if the inferred return type is a literal type (but not a literal union type) and the function does not have a contextual type with a return type that includes literal types, the return type is widened to its widened literal type.在没有返回类型注释的函数中,如果推断的返回类型是文字类型(但不是文字联合类型)并且该函数没有包含文字类型的返回类型的上下文类型,则返回类型扩展为它的扩展文字类型。

So this implies that in the case of "odd" | "even"所以这意味着在"odd" | "even" "odd" | "even" , you have a literal union type, which is not widened, while in the case of "" , you have a non-union literal type, which is widened. "odd" | "even" ,你有一个文字联合类型,它没有扩大,而在""的情况下,你有一个非联合文字类型,它扩大了。

As for why this rule is used as opposed to a simpler "never widen" rule, it's a heuristic that was chosen to minimize surprise in "normal" circumstances.至于为什么使用这条规则而不是更简单的“永不加宽”规则,这是一种启发式方法,被选择用来最大限度地减少“正常”情况下的意外。 Literal types are generally more useful in unions than standing alone, so the compiler assumes that function foo() {return "abc"} is more likely intended to return string , while function bar() {return Math.random<0.5? "abc": "def"}文字类型通常在联合中比单独使用更有用,因此编译器假设function foo() {return "abc"}更有可能返回string ,而function bar() {return Math.random<0.5? "abc": "def"} function bar() {return Math.random<0.5? "abc": "def"} is more likely intended to return a union of literals. function bar() {return Math.random<0.5? "abc": "def"}更有可能返回文字的联合。 As a heuristic it's not perfect, but it has apparently caused less surprise than alternatives would.作为一种启发式方法,它并不完美,但它显然比其他方法引起的意外要少。

There are various issues in GitHub where the current behavior is deemed to be working as intended; GitHub 中存在各种问题,其中当前行为被认为是按预期工作的; for example, see microsoft/TypeScript#51551 with this comment :例如,请参阅带有此注释microsoft/TypeScript#51551

The widening rules are in place to heuristically attempt to infer "better" types and different code is allowed to behave differently under these heuristics扩展规则已到位以试探性地尝试推断“更好”的类型,并且允许不同的代码在这些试探法下表现不同

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM