测试 case
type cases = [
Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Kars'>, true>>,
Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'>, false>>,
Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 7>, true>>,
Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 4>, false>>,
Expect<Equal<Includes<[1, 2, 3], 2>, true>>,
Expect<Equal<Includes<[1, 2, 3], 1>, true>>,
Expect<Equal<Includes<[{}], { a: 'A' }>, false>>,
Expect<Equal<Includes<[boolean, 2, 3, 5, 6, 7], false>, false>>,
Expect<Equal<Includes<[true, 2, 3, 5, 6, 7], boolean>, false>>,
Expect<Equal<Includes<[false, 2, 3, 5, 6, 7], false>, true>>,
Expect<Equal<Includes<[{ a: 'A' }], { readonly a: 'A' }>, false>>,
Expect<Equal<Includes<[{ readonly a: 'A' }], { a: 'A' }>, false>>,
Expect<Equal<Includes<[1], 1 | 2>, false>>,
Expect<Equal<Includes<[1 | 2], 1>, false>>,
Expect<Equal<Includes<[null], undefined>, false>>,
Expect<Equal<Includes<[undefined], null>, false>>,
]
- template.ts
type Includes<T extends readonly any[], U> = any
js 实现
方式1
const includes = (T: unknown[], U: unknown) => {
let result = false
for(let i = 0; i < T.length; i++) {
if (T[i] === U) {
result = true
}
}
return result
}
问题:
我们遍历数组必须要使用 In 关键字,但是in关键字只能在对象里使用,而我们又不需要返回对象,所以这种方案不适合
方式2
const includes2 = (T: unknown[], U: unknown) => {
if (T.length === 0) {
return false
}
const [first, ...reset] = T
if (first === U) {
return true
} else {
includes2(reset, U)
}
}
步骤
- 取出第一项,如果第一项等于 U 返回 true
- 不等于就递归
ts 实现
版本1
type Includes<T extends readonly any[], U> = T extends [infer First, ...infer Reset] ? First extends U ? true : Includes<Reset, U> : false
问题:
Expect<Equal<Includes<[boolean, 2, 3, 5, 6, 7], false>, false>>,
上面对于boolean 类型最为 First 的时候,因为 boolean 就相当于 false | true 的联合类型,First 又是一个变量类型,所以会走分布式条件语句就有得到 false => false = true true => false = false 所以结果是 true | false 也就是 boolean 解决方法给 First 和 U 都加一层[]
版本2
type Includes<T extends readonly any[], U> = T extends [infer First, ...infer Reset] ? [First] extends [U] ? true : Includes<Reset, U> : false
问题:
上面的代码虽然boolean的解决了,但是对于
{ a: 'A' } extends { readonly a: 'A' } => true
true extends boolean => true
而我们的用例里是期望 false
版本3
// 使用 IsEqual
type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T1>() => T1 extends B ? 1 : 2) ? true : false
type Includes<T extends readonly any[], U> = T extends [infer First, ...infer Reset] ? IsEqual<First, U> extends true ? true : Includes<Reset, U> : false
网友评论