awesome-typescript icon indicating copy to clipboard operation
awesome-typescript copied to clipboard

「重学TS 2.0 」TS 练习题第三十六题

Open semlinker opened this issue 3 years ago • 13 comments

实现一个 Filter 工具类型,用于根据类型变量 F 的值进行类型过滤。具体的使用示例如下所示:

type Filter<T extends any[], F> = // 你的实现代码

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]

请在下面评论你的答案

semlinker avatar Sep 22 '21 13:09 semlinker

type Filter<T extends any[], F, A extends any[] = []> = T extends [infer Head, ...infer Tail]
  ? Head extends F
    ? Filter<Tail, F, [...A, Head]>
    : Filter<Tail, F, A>
  : A;

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]

zhaoxiongfei avatar Sep 22 '21 15:09 zhaoxiongfei

这题容易遗漏的地方是,需要判断当前类型是否为 any,其他没什么难度

// 判断当前类型是否为 any
type IsAny<T> = 0 extends (1 & T) ? true : false 

// 实现一个 Filter 工具类型,用于根据类型变量 F 的值进行类型过滤。具体的使用示例如下所示:
type Filter<T extends any[], F> = T extends [infer R1, ...infer R2] 
  ? IsAny<R1> extends true
    ? [R1, ...Filter<R2, F>]
    : [...R1 extends F ? [R1] : [], ...Filter<R2, F>]
  : []

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]

xiaoYuanDun avatar Sep 23 '21 07:09 xiaoYuanDun

any 类型是个 ”黑洞“ 会吞噬除了 never 类型之外的大多数类型。本道题的关键点就是对 any 类型的处理。

type A0 = any & 1 // any
type A1 = any & boolean // any
type A2 = any & never // never

semlinker avatar Sep 23 '21 08:09 semlinker

type Filter<T extends any[], F, Result extends any[] = []> = T extends [
  infer H,
  ...infer R
]
  ? [H] extends [F]
    ? Filter<R, F, [...Result, H]>
    : Filter<R, F, [...Result]>
  : Result;

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]
const test2: F2 = [1, "abao"];

sunboyZgz avatar Sep 26 '21 01:09 sunboyZgz

  type Filter<T extends any[], F> =
    T extends [infer A, ...infer B] ? [A] extends [F] ? [A, ...Filter<B, F>] : Filter<B, F> : []

ln0y avatar Sep 28 '21 08:09 ln0y

type Filter<T extends any[], F, R extends any[] = []> = T extends [infer A, ...infer B]
  ? [A] extends [F]
    ? Filter<B, F, [...R, A]>
    : Filter<B, F, R>
  : R;

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]
type F3 = Filter<[never, number | string, any, "abao"], string>; // [never, any, "abao"]

思路: 利用 extends [infer A, ...infer B] 来提取数组内的第一项,递归这样就能提取到全部的,之后判断的类型的时候转换成元组类型[A] extends [F] 这样能避免出现的联合类型分发执行的问题。 never能匹配到任何类型上,这个题目没有说明,如果有说明的话,要特殊处理

zhaoxiongfei avatar Oct 03 '21 05:10 zhaoxiongfei

type Filter<T extends any[], F, R extends any[] = []> = T extends [infer A, ...infer B] ?  ([A] extends [F] ? Filter<B, F, [...R, A]> : Filter<B, F, R>) : R// 你的实现代码

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]

any extends others 会走true分支,也会走false分支

mingzhans avatar Oct 07 '21 06:10 mingzhans

// 可以把判断逻辑写在值里,能减少一次三元运算符的使用
type Filter<T extends any[], F, R extends F[] = []> = 
  T extends [infer A, ...infer B] 
  ? Filter<B, F, [A] extends [F] ? [...R, A] : R>
  : R

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]

Cxdhz avatar Nov 22 '21 13:11 Cxdhz

type Filter<T extends any[], F, U extends F[] = []> = T extends [infer A, ...infer Rest] ? [A] extends [F] ? Filter<Rest, F, [...U, A]> : Filter<Rest, F, U> : U // 你的实现代码

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7] type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"] type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]

jackwangwj avatar Dec 15 '21 02:12 jackwangwj

type Filter<T extends any[], V> = T extends [infer F, ...infer R]
  ? [F] extends [V]
    ? [F, ...Filter<R, V>]
    : Filter<R, V>
  : [];

zjxxxxxxxxx avatar Mar 24 '22 06:03 zjxxxxxxxxx

// 实现一个 Filter 工具类型,用于根据类型变量 F 的值进行类型过滤。具体的使用示例如下所示:
// type Filter<T extends any[], F> = // 你的实现代码
// type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
// type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
// type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]

//answer  🔔any、never为联合类型,使用[]包装阻止类型分发
type Filter<T extends any[], F, Result extends any[] = []> = T extends [infer N, ...infer L] ? (N[] extends F[] ? Filter<L, F, [...Result, N]> : Filter<L, F, Result>) : Result
type F0 = Filter<[6, 'lolo', 7, 'semlinker', false], number> // [6, 7]
type F1 = Filter<['kakuqo', 2, ['ts'], 'lolo'], string> // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, 'abao'], string> // [any, "abao"]

ChuTingzj avatar Jun 13 '22 13:06 ChuTingzj

type Filter<T extends any[], F, R extends any[] = []> = T extends [infer Head, ...infer Rest] ? Head extends F ? Filter<Rest, F, [...R, Head]> : Filter<Rest, F, R> : R;// 你的实现代码

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]

liziqiang avatar Jul 15 '22 09:07 liziqiang

type Filter<T extends any[], F, R extends F[] = []> = T extends [infer A, ...infer B] ?
  Filter<B, F, [A] extends [F] ? [...R, A] : R>
  : R

type F0 = Filter<[6, "lolo", 7, "semlinker", false], number>; // [6, 7]
type F1 = Filter<["kakuqo", 2, ["ts"], "lolo"], string>; // ["kakuqo", "lolo"]
type F2 = Filter<[0, true, any, "abao"], string>; // [any, "abao"]

dolphin0618 avatar Jul 23 '22 10:07 dolphin0618