【问题标题】:Does T[keyof T] work like the distributive conditional type?T[keyof T] 是否像分配条件类型一样工作?
【发布时间】:2020-12-16 03:02:25
【问题描述】:

我试图从Distributive conditional types 部分理解这个例子:

条件类型在与映射结合使用时特别有用 类型:

type FunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];

在这个例子中,index access 操作符的用法对我来说不是很清楚。 这是使用相同想法的最简单示例(据我所知):

type Foo = {
    prop1: never;
    prop2: never
    method1: "method1";
    method2: "method2";
}

type FunctionPropertyNames = Foo[keyof Foo] // "method1" | "method2"

所以,我的问题是:索引访问运算符的这种用法只是分布式条件类型的一种特殊情况吗?因为看起来结果类型是 T[K] 的所有应用程序的联合,其中 never 被过滤,因为 "never is the empty union"


更新。我将尝试更准确地表述这个问题: TS 手册描述了映射类型和条件类型的语法。 但是,我没有找到任何关于这种类型定义形式的描述:

type Keys = 'name1' | 'name2' | 'name3'
type Foo = Bar[Keys]

或者,更现实的:

type Foo = Bar[keyof Bar]

它看起来像某种映射,但它也提供过滤,在 Keys 包含never 的情况下。所以我的问题更多的是关于 TS 类型系统的这个特性是否有任何精确的描述。

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    这是一种特殊的用法,在根据属性类型过滤对象/类的属性时非常强大。这个article 很好地解释了如何方便地根据类实现与否来过滤类的联合(参见文章的Refining unions with distributive conditional types 部分)。

    其他用法

    正如您所说,索引访问运算符的这种用法的优势有助于从联合中删除不相关的类型,但它还有其他优势,例如根据特定条件更改类型。

    这是一个例子:

    type SchemaType<T> = {
      [k in keyof T]: T[k] extends
        | string
        | number
        | boolean
        | Types.ObjectId
        | Client
        | Doer
        | Mission
        | Date
        | Array<any>
        ? SchemaDefinition['']
        : SchemaType<T[k]>;
    };
    

    这是type,我用来输入我的猫鼬文档。

    我有一个打字稿 interface 定义什么是 User 和一个 document 描述 mongoDb 中的文档。

    我想要的是让document 实现与interface 相同的层次结构。

    例如,如果User 具有以下结构:

    interface User {
      id: Types.ObjectId;
      profile: {
        first_name: string;
      }
    }
    

    我希望 document 强制执行相同的并且类型安全:

    const schema: SchemaType<User> = {
      id: { type: Types.ObjectId },
      profile: {
        first_name: { type: String, default: '' },
      },
    };
    

    这就是SchemaType 与索引访问运算符的作用。如果该属性被视为叶类型(如 idfirst_name 是),则必须在文档中将其键入为 SchemaDefinition。如果它是一个对象,那么它必须像在 interface 中一样输入(这就是 SchemaType&lt;T[k]&gt; 所做的)。

    【讨论】:

    • 感谢您的回答和文章的链接。我昨天读了它,它包含一些非常好的解释。但是,我不确定它是否回答了我的问题。我会尝试更新它并更清楚地制定它。
    猜你喜欢
    • 1970-01-01
    • 2019-11-17
    • 2021-07-19
    • 2021-11-10
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    • 2021-08-26
    • 2016-07-31
    相关资源
    最近更新 更多