我试图使一个功能组件的反应,接受两个单独的字符串作为道具。是否有一种方法来确保这两个数组必须有相同的长度,使用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
)