TypeScript:如何确保一个函数组件的两个道具(都是数组)具有相同的长度?



我试图使一个功能组件的反应,接受两个单独的字符串作为道具。是否有一种方法来确保这两个数组必须有相同的长度,使用TypeScript?换句话说,当我们在其他组件中使用这个组件时,除非props的长度相同,否则我们将收到一个错误。

给你一个简单的例子,想象一下这样的东西:

export const TableView = ({ s1, s2 }: { s1: string[]; s2: string[] }) => {
return (
<table>
<thead>
<tr>
{s1.map((s, index) => {
return <th>{s1[index]}</th>;
})}
</tr>
</thead>
<tbody>
<tr>
{s2.map((s, index) => {
return <td>{s2[index]}</td>;
})}
</tr>
</tbody>
</table>
);
};

我想确保当我使用不同长度的字符串时,我看到一个错误。

<TableView s1={["1", "2", "3"]} s2={["1", "2", "3", "4"]} />
{/* show an error here */}

为了让编译器跟踪s1的长度和s2元素的输入参数,你应该让TableView通用s1的类型,然后用它来检查s2。因此,TableView的呼叫签名应该看起来像这样:

<T extends string[]>({ s1, s2 }: {
s1: [...T];
s2: [...{ [I in keyof T]: string; }];
}) => JSX.Element

这里我们说T是某种字符串数组类型,而s1本质上是T类型。语法[...T]使用可变元组类型语法给编译器一个提示,我们希望它将T解释为元组类型,而不仅仅是数组类型。元组类型有一个已知的顺序和长度,而普通数组类型没有。你关心的是长度,所以你想要一个元组类型。

如果我们可以为s2编写[...T]也会很好,但不幸的是,编译器会倾向于将T的元素推断为字符串文字类型,如"1""2",而不是string。如果是这样,说s2[...T],就等于限制了s2的每个元素必须完全等于s1的相应元素。我们不想拒绝{s1: ["1", "2"], s2: ["2", "1"]},所以我们不能这样做。

因此,我们说s2是一个映射元组类型,具有与s1相同数量的元素,但其中每个值类型都可以是string

这就是你想要的约束。


让我们测试一下:

<TableView s1={["1", "2", "3"]} s2={["4", "3", "2", "1"]} /> // error!
// --------------------------➨ ~~
// Source has 4 element(s) but target allows only 3.
<TableView s1={["1", "2", "3"]} s2={["4", "3", "2"]} /> // okay

看起来不错!

Playground链接到代码

您可以简单地在jsx中添加条件,如下所示:

export const TableView = ({ s1, s2 }: { s1: string[]; s2: string[] }) => {
return (
{s1.length === s2.length ?
<table>
<thead>
<tr>
{s1.map((s, index) => {
return <th>{s1[index]}</th>;
})}
</tr>
</thead>
<tbody>
<tr>
{s2.map((s, index) => {
return <td>{s2[index]}</td>;
})}
</tr>
</tbody>
</table>
:
<p> Error arrays are not the same length ...</p>
}
);
};

我想你可以在返回

之前使用下面的内容
if(sl.length !== s2.length) {
throw "Arrays are of different length"; //which throws custom exception
/*Or you can return anything that suits your needs*/
}
return(
//here goes your code
)

相关内容

  • 没有找到相关文章

最新更新