打字稿泛型-“扩展对象”毫无意义吗?最佳做法是啥?
Posted
技术标签:
【中文标题】打字稿泛型-“扩展对象”毫无意义吗?最佳做法是啥?【英文标题】:Typescript generics - is "extends object" pointless? What is the best practice?打字稿泛型-“扩展对象”毫无意义吗?最佳做法是什么? 【发布时间】:2021-05-02 19:46:30 【问题描述】:我注意到<P extends object>
泛型通常毫无意义,因为基本上javascript 中的所有内容都是一个对象。大多数文字是具有 .toString 方法的对象。字符串是具有 .length 属性等的对象。我开始更喜欢 <P>
但很好奇其他人注意到了什么。
我现在没有很好的例子,我只是想听听其他人的经验。
【问题讨论】:
我想不出extends object
不会是多余的情况,但我有兴趣学习其他方式。
实际上,string
does not extend object
,尽管String
确实如此。我投票结束,因为这个问题似乎是基于一个错误的前提。
<P extends any>
也是 tsx 文件的一种解决方法,以防止 被解释为 JSX 标记(尽管可以使用对象而不是任何对象进行映像)。如果没有意义,就不能真正权衡。我想如果P extends object
并且你试图将一个数字作为 P 传递它不会允许它虽然
<P,>
也可以在不引入约束的情况下工作
为了更详细,我注意到 typescript 将字符串解释为对象的情况,然后我拥有此类对象的所有这些不可靠的键 (toString | valueOf | toNumber | ...
)。还有@jcalz,感谢您的深入回答!我一直假设object
和
是相同的,但不知道Object
是一个实际类型
【参考方案1】:
更多信息请参见"The object
Type in TypeScript"。
TypeScript 中的 object
type 专门用于排除 primitive 七种类型,string
、number
、boolean
、bigint
、symbol
、undefined
和 null
。 (是的,typeof null === "object"
在运行时,但它在 JS 和 TS 中仍然被认为是原始的)。确实,string
、number
、boolean
、bigint
和 symbol
值将自动包装在 String
、Number
、Boolean
、BigInt
和 @987654@3 中对象(分别)当您访问它们上的成员时,就好像它们是对象一样。但它们可与真实物体区分开来,有时这会有所不同。 TypeScript 手册中给出的示例是 Object.create()
,如果传递原始类型的参数(null
除外),则会导致运行时错误。因此,TypeScript 对Object.create()
的键入指定其参数的类型为object | null
。如果您希望您的通用参数排除原语,<P extends object>
将是正确的方法......所以它不是毫无意义的。
请注意,TypeScript 中还有一个Object
接口,以大写的O
开头。该接口包含存在于 JS 中的所有内容上的(明显的)成员,例如 valueOf()
和 toString()
。当你说“一切都是对象”时,它可能更接近你的想法;只有null
和undefined
不能分配给Object
。不过一般来说,you probably don't want to use the Object
type in TypeScript;这种包装器类型几乎不是人们想要使用的。
如果你真的想捕捉“任何可以像对象一样被索引的东西”,你可能应该使用所谓的“空对象”类型,。这是一个没有已知属性的对象类型,其行为类似于
Object
。同样,只有null
和undefined
不能分配给。事实上,过去不受约束的泛型类型参数(如
<P>
而不是<P extends Q>
)被隐式约束为。所以过去写
<P extends >
是毫无用处的。
然而,从 TypeScript 3.5 开始,unconstrained generics are now given an implicit constraint of unknown
instead of 。
unknown
类型确实是 TypeScript 中的“一切”。您可以为unknown
类型的变量分配任何值(反之亦然)。写<P extends unknown>
真的没意义。
我们不妨以any
结尾,这是终极的“无所不能”类型。您不仅可以将任何内容分配给any
(例如unknown
),还可以将any
分配给任何内容(例如never
)。使用any
就像举手放弃;它更多的是禁用类型检查,而不是实际类型。 Since TypeScript 3.9,写<P extends any>
与写<P extends unknown>
相同,因此同样没有意义。 (过去,<P extends any>
允许您在 P
未解决时将 P
视为 any
,就像在通用函数实现中一样,但这被认为是愚蠢的并已更改。)
Playground link to code
【讨论】:
精彩而周到的回复,详尽地涵盖了询问者感兴趣的整个主题。谢谢!学到的比我正在寻找的要多得多! - 特别喜欢你对any
的定义:-D
you can also assign any to anything (like never)
好像不对。 Here is a playground link to code以上是关于打字稿泛型-“扩展对象”毫无意义吗?最佳做法是啥?的主要内容,如果未能解决你的问题,请参考以下文章