【问题标题】:Why can't I make this type generic? Type "x" cannot be used to index type "y" ts(2536)为什么我不能使这种类型通用?类型“x”不能用于索引类型“y”ts(2536)
【发布时间】:2021-07-18 07:05:01
【问题描述】:

我正在尝试编写一个泛型类型,它采用根级属性名称并返回嵌套在它下面的属性的联合类型。例如:

interface operations {
  updateSomething: {
    "201": {
      schema: number;
    };
    "400": {
      schema: string;
    };
  };
}

如果我想获得updateSomething 类型的“模式”,它应该解析为number | string。非通用版本工作正常:

type UpdateSomethingSchema =
  operations["updateSomething"][keyof operations["updateSomething"]]["schema"];

// string | number ✓

我编写泛型类型的尝试是:

type SchemaOf<
  O extends keyof operations
> = operations[O][keyof operations[O]]["schema"];

但这给了我一个错误:

Type '"schema"' cannot be used to index type 'operations[O][keyof operations[O]]'.ts(2536)

有趣的是,如果我忽略该错误,该类型似乎确实有效:

type UpdateSomethingSchema = SchemaOf<"updateSomething">;

// string | number ✓

是我做错了什么,还是 TypeScript 的限制?

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    我不知道为什么 TS 不能自己弄清楚,但它怀疑“模式”是该对象的关键之一,幸运的是在一点点鼓励下它可以工作:

    type SchemaOf<O extends keyof operations> = operations[O][keyof operations[O]]["schema" & (keyof operations[O][keyof operations[O]])];
    

    【讨论】:

    • 感谢您的帮助。这对我帮助很大,我认为我必须选择另一个答案作为正确答案,因为它稍微详细一些。
    【解决方案2】:

    您可以借助分布式条件类型来实现它:

    
    type Schema<T> = {
      schema: T
    }
    
    
    interface operations {
      updateSomething: {
        "201": Schema<number>;
        "400": Schema<string>;
      };
    }
    
    type SchemaOf<
      O extends keyof operations
      > = operations[O][keyof operations[O]] extends Schema<infer S> ? S : never
    
    type Result = SchemaOf<'updateSomething'> // string | number
    

    如果operations[O][keyof operations[O]] 推断出具有schema 属性的对象,TypeScript 能够推断出schema: T 的类型,并且由于分布性,它会返回一个联合类型。

    Distributive conditional types docs

    【讨论】:

    • 感谢您的帮助!我发现我可以在没有infer 的情况下达到同样的效果,只需这样做:T extends { schema: any } ? T["schema"] : never 但在某些情况下,infer 方法更简洁。
    猜你喜欢
    • 2018-11-04
    • 2021-10-24
    • 1970-01-01
    • 2023-01-20
    • 1970-01-01
    • 2022-11-11
    • 2022-11-15
    • 1970-01-01
    • 2018-04-01
    相关资源
    最近更新 更多