如何在元组中重用剩余类型?
How to reuse rest types in tuples?
function A<
NumArr extends [] | number[],
BoolArr extends [] | boolean[],
Params extends [...NumArr, "middle-element", ...BoolArr] = [...NumArr, "middle-element", ...BoolArr]
>(...arr: Params): Params {
return arr
}
//not a single error
const
test1: [1, false] = A(1, false),
test2: [false, "middle-element", 2] = A(false, "middle-element", 2),
test3: [] = A()
如何让TS检测Params
中元素的顺序是否符合要求?
或者只是解释为什么这段代码不符合直觉逻辑。
对于 TypeScript 来说,这不是一项简单的任务。休息参数不以您期望的方式工作后的休息参数。事实上,论点只是推断出来的,并没有得到验证。不幸的是,您应该自己编写验证逻辑。
进入正题。
考虑这个例子:
type Elem = number | boolean | "middle-element";
type Last<T extends any[]> = T extends [infer _]
? never
: T extends [...infer _, infer Tl]
? Tl
: never
type HandleEmpty<T extends any[], Data> = T['length'] extends 0 ? never : Data
type Validation<Params extends any[], Cache extends Elem[] = []> =
Params extends []
? Cache['length'] extends 0
? never
: Cache
: Params extends [infer Fst, ...infer Rest]
? Cache extends []
? Fst extends number
? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>
: never
: Fst extends number
? Last<Cache> extends number
? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>
: never
: Fst extends "middle-element"
? Last<Cache> extends number
? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>
: never
: "middle-element" extends Cache[number]
? Fst extends boolean
? Validation<Rest, [...Cache, Fst]>
: never
: never
: never
{
type Test = Validation<[42, 43, "middle-element", false, true]> // ok
type Test2 = Validation<[42, "middle-element", true, false]> // ok
type Test3 = Validation<[false, "middle-element", 42]> // never
type Test4 = Validation<[42, false]> // never
type Test5 = Validation<[false, false, false, "middle-element", 42, "middle-element", 43]> //never
type Test6 = Validation<[false, false, false, "middle-element", 42, false, 43]> // never
type Test7 = Validation<[false, 42, "middle-element"]> // never
type Test8 = Validation<[false, "middle-element", 42, false, "middle-element", 42,]> // never
type Test9 = Validation<[false, "middle-element"]> // never
type Test10 = Validation<[false]> // never
type Test11 = Validation<[]> // never
type Test12 = Validation<[42, "middle-element", boolean, "middle-element", 43]> //never
type Test13 = Validation<[2, false, "middle-element"]> // never
}
type IsNever<T> = [T] extends [never] ? true : false;
function check<
Params extends Elem[],
IsValid extends Validation<Params>
>(...arr: IsNever<IsValid> extends true ? [never] : [...Params]) {
return arr
}
/**
* Ok
*/
const valid = check(1, 'middle-element', false)
const valid2 = check(1, 42, 43, 67, 'middle-element', false, true, false)
/**
* Errors
*/
const test2 = check(false, "middle-element", 2)
const test1 = check(1, false)
const test3 = check()
我了解 Validation
实用程序类型根本不可读。
这里有 js 表示。请把它当作一个解释。我不知道这段代码在tuntime中是否可以:
const last = (data: any) => data[data.length - 1]
const handleEmpty = (data: any[], defaultValue) => data.length === 0 ? null : defaultValue
const never = null;
const validation = (params: any[], cache: any[] = []): any[] | null => {
if (params.length === 0 && cache.length === 0) {
return never // never is null
}
const [fst, ...rest] = params;
if (cache.length === 0) {
if (typeof fst === 'number') {
return handleEmpty(rest, validation(rest, [...cache, fst]))
} else {
return never
}
}
if (typeof fst === 'number') {
return handleEmpty(rest, validation(rest, [...cache, fst]))
}
if (typeof fst === "middle-element") {
if (typeof last(cache) === 'number') {
return handleEmpty(rest, validation(rest, [...cache, fst]))
}
return null
}
if (cache.includes('middle-element')) {
if (typeof fst === 'boolean') {
return handleEmpty(rest, validation(rest, [...cache, fst]))
}
}
return never
}
正如您可能已经注意到的那样,有很多 if 条件语句,但它非常简单且合乎逻辑。
我还包括了几个 Validation
实用程序类型的测试。你可以写更多。由你决定。
function A<
NumArr extends [] | number[],
BoolArr extends [] | boolean[],
Params extends [...NumArr, "middle-element", ...BoolArr] = [...NumArr, "middle-element", ...BoolArr]
>(...arr: Params): Params {
return arr
}
//not a single error
const
test1: [1, false] = A(1, false),
test2: [false, "middle-element", 2] = A(false, "middle-element", 2),
test3: [] = A()
如何让TS检测Params
中元素的顺序是否符合要求?
或者只是解释为什么这段代码不符合直觉逻辑。
对于 TypeScript 来说,这不是一项简单的任务。休息参数不以您期望的方式工作后的休息参数。事实上,论点只是推断出来的,并没有得到验证。不幸的是,您应该自己编写验证逻辑。
进入正题。
考虑这个例子:
type Elem = number | boolean | "middle-element";
type Last<T extends any[]> = T extends [infer _]
? never
: T extends [...infer _, infer Tl]
? Tl
: never
type HandleEmpty<T extends any[], Data> = T['length'] extends 0 ? never : Data
type Validation<Params extends any[], Cache extends Elem[] = []> =
Params extends []
? Cache['length'] extends 0
? never
: Cache
: Params extends [infer Fst, ...infer Rest]
? Cache extends []
? Fst extends number
? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>
: never
: Fst extends number
? Last<Cache> extends number
? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>
: never
: Fst extends "middle-element"
? Last<Cache> extends number
? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>
: never
: "middle-element" extends Cache[number]
? Fst extends boolean
? Validation<Rest, [...Cache, Fst]>
: never
: never
: never
{
type Test = Validation<[42, 43, "middle-element", false, true]> // ok
type Test2 = Validation<[42, "middle-element", true, false]> // ok
type Test3 = Validation<[false, "middle-element", 42]> // never
type Test4 = Validation<[42, false]> // never
type Test5 = Validation<[false, false, false, "middle-element", 42, "middle-element", 43]> //never
type Test6 = Validation<[false, false, false, "middle-element", 42, false, 43]> // never
type Test7 = Validation<[false, 42, "middle-element"]> // never
type Test8 = Validation<[false, "middle-element", 42, false, "middle-element", 42,]> // never
type Test9 = Validation<[false, "middle-element"]> // never
type Test10 = Validation<[false]> // never
type Test11 = Validation<[]> // never
type Test12 = Validation<[42, "middle-element", boolean, "middle-element", 43]> //never
type Test13 = Validation<[2, false, "middle-element"]> // never
}
type IsNever<T> = [T] extends [never] ? true : false;
function check<
Params extends Elem[],
IsValid extends Validation<Params>
>(...arr: IsNever<IsValid> extends true ? [never] : [...Params]) {
return arr
}
/**
* Ok
*/
const valid = check(1, 'middle-element', false)
const valid2 = check(1, 42, 43, 67, 'middle-element', false, true, false)
/**
* Errors
*/
const test2 = check(false, "middle-element", 2)
const test1 = check(1, false)
const test3 = check()
我了解 Validation
实用程序类型根本不可读。
这里有 js 表示。请把它当作一个解释。我不知道这段代码在tuntime中是否可以:
const last = (data: any) => data[data.length - 1]
const handleEmpty = (data: any[], defaultValue) => data.length === 0 ? null : defaultValue
const never = null;
const validation = (params: any[], cache: any[] = []): any[] | null => {
if (params.length === 0 && cache.length === 0) {
return never // never is null
}
const [fst, ...rest] = params;
if (cache.length === 0) {
if (typeof fst === 'number') {
return handleEmpty(rest, validation(rest, [...cache, fst]))
} else {
return never
}
}
if (typeof fst === 'number') {
return handleEmpty(rest, validation(rest, [...cache, fst]))
}
if (typeof fst === "middle-element") {
if (typeof last(cache) === 'number') {
return handleEmpty(rest, validation(rest, [...cache, fst]))
}
return null
}
if (cache.includes('middle-element')) {
if (typeof fst === 'boolean') {
return handleEmpty(rest, validation(rest, [...cache, fst]))
}
}
return never
}
正如您可能已经注意到的那样,有很多 if 条件语句,但它非常简单且合乎逻辑。
我还包括了几个 Validation
实用程序类型的测试。你可以写更多。由你决定。