TypeScript:`| 的含义[T]`-用于数组中元素成员资格的编译时检查的约束
TypeScript: Meaning of `| [T]`-constraint for compile-time checks of element membership in arrays
我想编写一个函数 f
接受类型 A
的单个参数,其中 A
必须是包含特定类型元素的数组 T
.为简单起见,假设 T = 'ok'
(字符串的单例类型 'ok'
)。
借鉴的思路,初步得到如下解决方案:
function f<
E,
A extends (ReadonlyArray<E> | [E]) & {[K in keyof A]: {[T in K]: 'ok'}}[number]
>(a: A) {}
正如上面引用的答案,它确实有效。
但是我无法理解 | [E]
部分,所以我决定检查是否可以删除它,或者用另一种类型替换它:
function f<
E,
X,
A extends (ReadonlyArray<E> | [X]) & {[K in keyof A]: {[T in K]: 'ok'}}[number]
>(a: A) {}
这也有效,即它可以区分有或没有元素的数组 'ok'
:
f(['a', 'b', 'ok', 'z']) // compiles, good
f(['a', 'b', 'z']) // does not compile, good
我的问题是我无法理解为什么删除 [X]
部分后它不起作用。它似乎与代码中发生的任何事情完全无关:
[X]
的元数与元组的元数不匹配
- 类型
X
实际上没有绑定到任何东西,它没有包含 E
或 A
或 string
或 'ok'
或还有什么。
| [X]
到底在做什么?
举个简单的例子:
function foo<T extends number[]>(t: T): T { return t }
foo([1, 2, 3]) // number[]
将有一个数组 return 类型推断。
function foo2<T extends number[] | [number]>(t: T): T { return t }
foo2([1, 2, 3]) // [number, number, number]
| [number]
forces TypeScript to infer a tuple 而不是数组,不使用 as const
(隐藏的编译器规则,如果你愿意的话)。
您甚至可以通过为扩展原始类型的数组项添加类型参数 R
来缩小数字字面量:
function foo3<R extends number, T extends R[] | [R]>(t: T): T { return t }
foo3([1, 2, 3]) // [1, 2, 3]
我想编写一个函数 f
接受类型 A
的单个参数,其中 A
必须是包含特定类型元素的数组 T
.为简单起见,假设 T = 'ok'
(字符串的单例类型 'ok'
)。
借鉴
function f<
E,
A extends (ReadonlyArray<E> | [E]) & {[K in keyof A]: {[T in K]: 'ok'}}[number]
>(a: A) {}
正如上面引用的答案,它确实有效。
但是我无法理解 | [E]
部分,所以我决定检查是否可以删除它,或者用另一种类型替换它:
function f<
E,
X,
A extends (ReadonlyArray<E> | [X]) & {[K in keyof A]: {[T in K]: 'ok'}}[number]
>(a: A) {}
这也有效,即它可以区分有或没有元素的数组 'ok'
:
f(['a', 'b', 'ok', 'z']) // compiles, good
f(['a', 'b', 'z']) // does not compile, good
我的问题是我无法理解为什么删除 [X]
部分后它不起作用。它似乎与代码中发生的任何事情完全无关:
[X]
的元数与元组的元数不匹配- 类型
X
实际上没有绑定到任何东西,它没有包含E
或A
或string
或'ok'
或还有什么。
| [X]
到底在做什么?
举个简单的例子:
function foo<T extends number[]>(t: T): T { return t }
foo([1, 2, 3]) // number[]
将有一个数组 return 类型推断。
function foo2<T extends number[] | [number]>(t: T): T { return t }
foo2([1, 2, 3]) // [number, number, number]
| [number]
forces TypeScript to infer a tuple 而不是数组,不使用 as const
(隐藏的编译器规则,如果你愿意的话)。
您甚至可以通过为扩展原始类型的数组项添加类型参数 R
来缩小数字字面量:
function foo3<R extends number, T extends R[] | [R]>(t: T): T { return t }
foo3([1, 2, 3]) // [1, 2, 3]