【问题标题】:Significance of "extends {}"“扩展 {}”的意义
【发布时间】:2020-10-14 14:04:34
【问题描述】:

在现有代码中,我遇到过这样的类型参数声明:<Param extends {}>

我的问题是,extends {} 部分的含义是什么?它与简单的<Param> 有何不同?


例子:

type Fold<S extends {}, D extends {}> = {
  folder: ...
}

【问题讨论】:

  • 没有代码很难说,可能是为了防止字符串、数字、未定义等原始类型……你有例子吗?
  • @HTN:这不排除原语,object 会这样做。
  • @HTN it doesn't prevent primitives。不过,我实际上不知道它的作用。这绝对是任何事物的下限。可能会阻止never,不确定。
  • doesn't filter out never, either。我也很好奇这种用法。可能只是 something 之前存在但后来被移除的人工制品。或者一种模式,以便您将来可以快速填写属性。
  • @ford04 加了个例子,够了吗?

标签: typescript typescript-generics


【解决方案1】:

{}unknown 约束

如果你写 &lt;S&gt;S 就是 unconstrained - 它是 behaves like &lt;S extends unknown&gt; (TS 3.5+)。

{} 类型可以接受每个值(包括原语),除了 nullundefinedstrictNullChecks

unknown 或多或少是{} | null | undefined,使{} 成为更窄的子类型:

type FoldImplicit<S> = S
type FoldObject<S extends {}> = S

type T1 = FoldImplicit<"foo"> // ✅ 
type T2 = FoldImplicit<undefined> // ✅
type T3 = FoldObject<"foo"> // ✅
type T4 = FoldObject<undefined> // ❌ - `undefined` not in `{}` (strictNullChecks)
// compiles with `strictNullChecks` disabled 
// - null and undefined now belong to every type.

我在哪里可以看到这些构造?

最常遇到的情况大概是React generic components:

// help compiler to distinguish JSX tag from generic component declaration
const Comp = <T extends {}>(props: { foo: T }) => <div>...</div>

要更紧密地匹配implicit constraints,您可以写&lt;T extends unknown&gt; 或只写&lt;T,&gt;(注意逗号)。在 TS 3.5 之前,隐式约束一直是{}

使用extends {},您还可以带走undefinednull 作为可能的输入。但在我看来 a) 它使代码不必要地冗长 b) 你最好为更强的类型找到更窄的约束。

Playground sample

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    • 2019-06-21
    • 1970-01-01
    • 2021-12-08
    • 2012-02-22
    • 1970-01-01
    相关资源
    最近更新 更多