1

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

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 今天不支持这样的推断,但有没有另一种方法可以用来根据另一个属性的值来限制一个属性的类型?

感谢您的任何建议!

4

1 回答 1

0

为此,您需要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
}

操场

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-10-29T09:32:30.373 回答