确保Typescript数组具有特定值

lvjbypge  于 2023-02-05  发布在  TypeScript
关注(0)|答案(1)|浏览(203)

我正在构建一个下拉样式的组件,值和选项是不同的属性。我希望使用Typescript来确保值是有效的选项。虽然我可以在运行时做这个检查,但我觉得这是我应该能够在TS中做的事情。
这可能吗?

interface Props<N extends number> {
    count: N,
    options: Array<N | number> // Tuples don't work here, since this can be any length
}

const Component = <N extends number>({count, options} : Props<N>) => {
  // We could do a runtime check to verify that `count` is in `options`, but I'd rather do the check earlier if possible
}

Component({count: 5, options: [1,2,3]}) // This should be an error
bvjxkvbb

bvjxkvbb1#

其思想是将字面类型countoptions都推断为泛型类型NO。但是对于O,我们需要提示编译器来推断数字文字的元组类型,而不仅仅是number[]。我们可以通过将O Package 成一个可变元组类型(看起来像[...O])来实现这一点。
为了实现验证,我们可以使用一个 conditional type 来检查N是否是O[number]的成员。如果它不是成员,则条件解析为never,导致错误,因为不能为never赋值。

interface Props<N extends number, O extends readonly number[]> {
  count: N;
  options: N extends O[number] ? readonly [...O] : never;
}
const Component = <N extends number, O extends readonly number[]>({
  count,
  options,
}: Props<N, O>) => {};

只要作为options传递的数组是tuple类型,这就可以正常工作。

Component({ count: 5, options: [1, 2, 3] }); // error

Component({ count: 5, options: [1, 2, 3, 5] }); // ok

Component({ count: 5, options: [] as number[] }); 
// ok, all the elements in options are number and 5 does extend number :/

如果options是数组类型,则其元素的类型为number,并且5确实扩展了numbernumber最终通过类型检查。
Playground

相关问题