首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可推断所有值的类型签名

可推断所有值的类型签名
EN

Stack Overflow用户
提问于 2020-09-25 01:28:43
回答 2查看 192关注 0票数 3

这在TypeScript 4.0.2中。类型系统可以从下面示例中的类型签名推断出一些值。我很困惑,为什么它不能推断出const b中最后一个元素的具体值。

有人能解释为什么,以及我如何写一个类型的签名,可以吗?

代码语言:javascript
复制
declare function identityA<T extends string[]>(p: readonly [...T]): T
declare function identityB<T extends any[]>(p: readonly [...T]): [...T]

const a = identityA(['r', 's'])  // ['r', 's']
const b = identityB([...a, 3])  // ['r', 's', number]
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-09-25 02:23:39

TypeScript的类型推断使用各种启发式方法来确定何时扩大文字类型,以及何时使它们尽可能狭窄。例如,当你写

代码语言:javascript
复制
let s = ""; // string
let n = 0; // number
let b = true; // boolean

变量snb的类型分别扩展为stringnumberboolean。假设是,由于let声明允许您重新分配值,所以您可能希望这样做。另一方面,当你写

代码语言:javascript
复制
const sC = ""; // ""
const nC = 0; // 0
const bC = true; // true

变量sCnCbC的类型分别保持为""0true。假设因为不能更改这些值,所以没有理由允许类型中的单个值更多。

对于类型参数,如TidentityA()identityB()函数中,编译器会执行其他操作。在微软/打字稿#10676中提到了这一点

在调用表达式的类型参数推断期间,如果(.) T没有约束,或者它的约束不包括原语或文字类型,则将类型参数T的推断类型拓宽为其扩大的文字类型

在……里面

代码语言:javascript
复制
declare function identityA<T extends string[]>(p: readonly [...T]): T

类型参数T有一个包含基本string类型的约束,因此T不会从["r", "s"]扩展到[string, string]。另一方面,在

代码语言:javascript
复制
declare function identityB<T extends any[]>(p: readonly [...T]): [...T]

类型参数T的约束不包括任何文字或原始类型,因此T将从(比方说) [3]扩展到[number],或者由于"r""s"类型已经从以前的推断中没有扩展,T将从["r", "s", 3]扩展到["r", "s", number]

这很让人困惑对吧?没关系,通过在您的多元元组类型参数类型中使用p [...T],您将提示编译器您希望推断元组类型 for T,而不仅仅是数组类型。

所以这就是它发生的原因。你能做些什么来修复它?

如果您控制了调用站点,您可以使用断言显式地要求编译器为您传递的内容推断最窄的类型。这发生在T推断之前:

代码语言:javascript
复制
const iBAsConst = identityB([...iA, 3] as const)  // ['r', 's', 3]

但是,您询问了如何更改签名以将identityB()的类型参数转换为文字偏好推理工具。您可以通过将any[]更改为包含原语的内容来做到这一点。例如:

代码语言:javascript
复制
type Narrowable = string | number | boolean | symbol | 
  object | undefined | void | null | {};
declare function identityC<T extends Narrowable[]>(p: readonly [...T]): [...T]
const iC = identityC(["r", "s", 3]); // ['r', 's', 3] 

几乎任何东西都可以分配给Narrowable,就像一个奇怪的anyunknown,它也可以作为一个保持-这个-狭窄的提示。

万岁对吧?

如果这一切在你看来都是邪恶的魔法,我同意。不久前,我打开微软/打字稿#30680请求一些语法,以显式地请求函数的签名端的"as const"-like行为。然后你就可以写些东西

代码语言:javascript
复制
// don't try this, it won't work:
declare function identityB<T extends any[] as const>(p: readonly [...T]): [...T];

才能达到同样的效果。唉,这只是今天(2020-09-24)的一个建议,所以现在你必须继续练习黑暗艺术,才能得到你想要的推论。

操场链接到代码

票数 6
EN

Stack Overflow用户

发布于 2020-09-25 01:33:44

如果将参数标记为identityB as const,TS可以将元组参数中的项的类型缩小到它们的文字类型。否则,它只使用typeof --最后一个参数。

代码语言:javascript
复制
declare function identityA<T extends string[]>(p: readonly [...T]): T
declare function identityB<T extends any[]>(p: readonly [...T]): [...T]

const a = identityA(['r', 's'])  // ['r', 's']
const b = identityB([...a, 3] as const)  // ['r', 's', 3] 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64056538

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档