【问题标题】:Infer generic from properties从属性推断泛型
【发布时间】:2021-12-14 09:20:39
【问题描述】:

让我们有一个界面来描述带有示例结果的评级表单,以预览在所有参与者提交表单后它的外观:

interface Rating {
  maxRating: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
  exampleResults: number[]; // E.g. [0, 0, 0, 2, 5] = 2 votes for 4*, 5 votes for 5*.
}

这个幼稚的实现不会检查exampleResults 的长度是否与maxRating 的值相同。所以我尝试了:

interface Rating<T extends 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10> {
  maxRating: T;
  exampleResults: Tuple<number, T>; // Touple definition is omitted for simplification
}

但是当我尝试使用它时:

const rating: Rating = {
  maxRating: 5,
  exampleResults: [0, 0, 0, 1, 4],
}

我收到此错误:

通用类型“评级”需要 1 个类型参数。

但显然 TypeScript可以通过读取 maxRating 的值来推断类型。

如果 TypeScript 今天不支持这种推断,我现在知道了,但是我可以使用另一种方法来根据另一个属性的值来限制一个属性的类型吗?

感谢您的任何建议!

【问题讨论】:

    标签: typescript type-inference


    【解决方案1】:

    为此,您需要提前推断/了解maxRating。考虑这个例子:

    type Max = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
    
    type Tuple<Length extends Max, Result extends number[] = []> =
      Result['length'] extends Length
      ? Result
      : Tuple<Length, [...Result, number]>
    
    interface Rating<M extends Max> {
      maxRating: M
      exampleResults: Tuple<M>
    }
    
    const rating: Rating<5> = {
      maxRating: 5,
      exampleResults: [1, 2, 3, 4, 5] // ok
    }
    
    const rating2: Rating<5> = {
      maxRating: 5,
      exampleResults: [1, 2, 3, 4, 5, 6] // expected error
    }
    

    Playground

    TypeScript 无法像您一样从对象推断出 maxRating

    还有另一种推断maxRating的方法。你可以使用一个函数:

    const handler = <N extends Max>(r: Rating<N>) => r
    
    handler({ maxRating: 10, exampleResults: [1, 2, 3, 4, 5, 0, 0, 0, 0, 0] }) // ok
    

    【讨论】:

      猜你喜欢
      • 2021-09-29
      • 1970-01-01
      • 2021-06-11
      • 1970-01-01
      • 2010-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      相关资源
      最近更新 更多