Javascript 混合类型的数组,但在数组中具有特定类型的最小计数
假设我想对给定数组强制执行严格的类型输入,这样:Javascript 混合类型的数组,但在数组中具有特定类型的最小计数,javascript,arrays,typescript,Javascript,Arrays,Typescript,假设我想对给定数组强制执行严格的类型输入,这样: 它可以包含number 它必须包含一个或多个字符串 …并且数组中number和string的顺序无关紧要,因此以下数组是有效的: ['foo',1,2,3] [1,2,'foo',3] ['foo'] 但以下数组无效: [1,2,3](因为它在数组中至少需要一个字符串) 最接近我的解决方案是将类型定义为: /** * Array must contain: * - One or more string * - Zero or m
- 它可以包含
number
- 它必须包含一个或多个
字符串
number
和string
的顺序无关紧要,因此以下数组是有效的:
['foo',1,2,3]
[1,2,'foo',3]
['foo']
(因为它在数组中至少需要一个[1,2,3]
字符串)
/**
* Array must contain:
* - One or more string
* - Zero or more numbers
* @type
*/
type CustomArray = [string] & Array<number | string>
const a: CustomArray = ['foo', 1, 2, 3]; // Should pass (works as expected)
const b: CustomArray = [1, 2, 'foo', 3]; // Should pass (but doesn't with my code)
const c: CustomArray = ['string']; // Should pass (works as expected)
const d: CustomArray = [1, 2, 3]; // Should fail (works as expected)
/**
*数组必须包含:
*-一个或多个字符串
*-零个或多个数字
*@type
*/
键入CustomArray=[string]&数组
常量a:CustomArray=[foo',1,2,3];//应通过(按预期工作)
常量b:CustomArray=[1,2,'foo',3];//应该通过(但与我的代码不一致)
常量c:CustomArray=['string'];//应通过(按预期工作)
常量d:CustomArray=[1,2,3];//应失败(按预期工作)
但这意味着数组的第一个元素必须是字符串,而不是在整个数组中强制执行最小计数1 无法告诉TypeScript数组应该至少包含一个特定类型的元素 您只能创建一个数字/字符串数组:
type CustomArray = (number | string)[];
或
类型CustomArray=Array;
然后在向数组添加数据或从数组中读取数据的位置添加数据。这是个好主意吗
/**
*数组必须包含:
*-一个或多个字符串
*-零个或多个数字
*@type
*/
console.clear();
常量CustomArray=(arr:Array)=>{
如果(!arr.length){
返回新的TypeError(“无效:数组应至少包含一个元素”);
}
const oneString=arr.filter(v=>v.constructor==String);
const errowtypes=arr.filter(v=>v.constructor!==Number&&v.constructor!==String);
如果(错误类型){
返回新类型错误(`Invalid:[${JSON.stringify(arr)}]包含无效类型`);
}
如果(!oneString){
返回新的TypeError(`Invalid:[${JSON.stringify(arr)}]应至少包含一个字符串值`);
}
返回arr;
};
类型MyArray=Array |类型错误;
常量a:MyArray=CustomArray(['foo',1,2,3]);//应通过(按预期工作)
常量b:MyArray=CustomArray([1,2,'foo',3]);//应通过(按预期工作)
常量c:MyArray=CustomArray(['string']);//应通过(按预期工作)
常量d:MyArray=CustomArray([1,2,3]);//应失败(按预期工作)
常量日志=(v:any)=>
log(v instanceof TypeError?v.message:JSON.stringify(v));
日志(a);
日志(b);
对数(c);
对数(d)代码>对于具有特定类型的最小大小的数组,似乎无法进行编译时检查
以下是基于运行时检查的解决方案:
我将引入字符串和数字的元组,而不是使用不同类型的数组
type Custom = [number[], string[]];
然后,您可以定义一个检查函数,查看它是否满足您的要求:
const isValid = (c: Custom): boolean => {
const [_, strings] = c;
return strings.length >= 1;
};
如果需要将输入作为数组,可以将其转换为元组:
const toCustom = (a: (string | number)[]): Custom => {
const numbers: number[] = [];
const strings: string[] = [];
a.forEach((element) => {
if (typeof element === "string") {
strings.push(element);
} else if (typeof element === "number") {
numbers.push(element);
} else {
throw new Error("Unexpected type given"); // for runtime errors
}
});
return [
numbers,
strings
];
}
然后您可以强制执行运行时检查:
const a = isValid(toCustom([
"foo",
1,
2,
3
])); // Should pass
const b = isValid(toCustom([
1,
2,
"foo",
3
])); // Should pass
const c = isValid(toCustom(["string"])); // Should pass
const d = isValid(toCustom([
1,
2,
3
])); // should fail
console.log(a, b, c, d); // prints: true true true false
可能有一种方法可以强制设置数组的最小大小,但它只适用于元组方法:
type OneOrMore<T> = {
0: T
} & T[]
type Custom = [number[], OneOrMore<string>];
const bar: Custom = [
[
1,
2,
3
],
["bar"],
];
const foo: Custom = [
[
1,
2,
3
],
[], // missing zero property
];
键入一个或多个={
0:T
}&T[]
键入Custom=[number[],一个或多个];
常量栏:自定义=[
[
1.
2.
3.
],
[“酒吧],
];
常量foo:自定义=[
[
1.
2.
3.
],
[],//缺少零属性
];
使用定制型防护装置是否可行?相关:添加一个和{u isCustomArray:true}
,然后用复选框进行类型转换。@Jonaswillms:这将如何验证至少有一个字符串项的要求?函数asCustomArray(array:(string | number)[]):CustomArray | never{…
。。。。或者只是使用自定义类型保护?…虽然这不会在运行前进行严格的类型检查。那么为什么不使用CustomArray
而不是MyArray
?arr as MyArray
就有意义了。还返回一个错误真的很难看谢谢你的回答!然而,我并不是在寻找一个进行这种检查的函数:只是一个满足需求的类型定义。看来现在不可能了。@Terry,没问题。我必须承认,我很少觉得有必要使用打字稿。谢谢你的回答!然而,我并不是在寻找一个进行这种检查的函数:只是一个满足需求的类型定义。看来现在不可能了。
type OneOrMore<T> = {
0: T
} & T[]
type Custom = [number[], OneOrMore<string>];
const bar: Custom = [
[
1,
2,
3
],
["bar"],
];
const foo: Custom = [
[
1,
2,
3
],
[], // missing zero property
];