Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

「重学TS 2.0 」TS 练习题第二十八题 #47

Open
semlinker opened this issue Sep 20, 2021 · 15 comments
Open

「重学TS 2.0 」TS 练习题第二十八题 #47

semlinker opened this issue Sep 20, 2021 · 15 comments

Comments

@semlinker
Copy link
Owner

实现一个 Split 工具类型,根据给定的分隔符(Delimiter)对包含分隔符的字符串进行切割。可用于定义 String.prototype.split 方法的返回值类型。具体的使用示例如下所示:

type Item = 'semlinker,lolo,kakuqo';

type Split<
	S extends string, 
	Delimiter extends string,
> = // 你的实现代码

type ElementType = Split<Item, ','>; // ["semlinker", "lolo", "kakuqo"]

请在下面评论你的答案。

@suica
Copy link

suica commented Sep 20, 2021

type Item = 'semlinker,lolo,kakuqo';

type Split<
	S extends string, 
	Delimiter extends string,
> = S extends `${infer A}${Delimiter}${infer B}` ? [A,...Split<B,Delimiter>] : [S];

type ElementType = Split<Item, ','>; // ["semlinker", "lolo", "kakuqo"]

@zhaoxiongfei
Copy link

type Item = "semlinker,lolo,kakuqo";

type Split<
  S extends string,
  Delimiter extends string,
> = S extends `${infer First}${Delimiter}${infer Rest}` ? [First, ...Split<Rest, Delimiter>] : [S];

type ElementType = Split<Item, ",">; // ["semlinker", "lolo", "kakuqo"]

@xiaoYuanDun
Copy link

xiaoYuanDun commented Sep 23, 2021

和 29 题一样

type Split<
  S extends string, 
  Delimiter extends string,
  R extends any[] = []   //  记录遍历记录
> = 
S extends `${infer R1}${Delimiter}${infer R2}` 
  ? Split<R2, Delimiter, [...R, R1]>   //  记录R1, 继续遍历剩余部分
  : [...R, S]                          //  没有更多的 Delimiter 了, 直接记录当前的 S 并返回

type ElementType1 = Split<'semlinker,lolo,kakuqo', ','>; // ["semlinker", "lolo", "kakuqo"]
type ElementType2 = Split<'dog=1&cat=2&pig=34', '&'>; // ["dog=1", "cat=2", "pig=34"]

@pingan8787
Copy link

题解

这题只要会用 ${infer X}${S}${infer Y} 这种写法就很方便了,意思是将一个字符串做拆解:

type Item = 'semlinker,lolo';

type Test<
	S extends string, 
	Delimiter extends string,
> = S extends `${infer Key}${Delimiter}${infer Rest}` 
  ? [Key, Rest] 
  : [S]

type TestElement = Test<Item, ','>; // ["semlinker", "lolo"]

这边 Key 对应 "semlinker"Delimiter 对应 ,Rest 对应 "lolo",这个理解了,再看这题解法就比较简单了,也是使用递归:

type Item = 'semlinker,lolo,kakuqo';

type Split<
	S extends string, 
	Delimiter extends string,
> = S extends `${infer Key}${Delimiter}${infer Rest}` 
  ? [Key, ...Split<Rest, Delimiter>] 
  : [S]

type ElementType = Split<Item, ','>; // ["semlinker", "lolo", "kakuqo"]
type ElementType2 = Split<'a|b|c||d', '|'>; // ["a", "b", "c", "", "d"]
type ElementType3 = Split<'abcdef', ''>; // ["a", "b", "c", "d", "e", "f", ""]

这边细心的朋友会发现 ElementType3 的值最后多出了 "",因为在最后一个位置,取到的 Rest 是空字符串,所以这边我们就需要再做处理,过滤掉空字符串:

type Split<
	S extends string, 
	Delimiter extends string,
> = S extends `${infer Key}${Delimiter}${infer Rest}` 
  ? [Key, ...Split<Rest, Delimiter>] 
  : S extends ''   /* 处理空字符串 */
  ? [] 
  : [S]

type ElementType = Split<Item, ','>; // ["semlinker", "lolo", "kakuqo"]
type ElementType2 = Split<'a|b|c||d', '|'>; // ["a", "b", "c", "", "d"]
type ElementType3 = Split<'abcdef', ''>; // ["a", "b", "c", "d", "e", "f"]

这样就能去掉最后一个 "" 了。

@zhaoxiongfei
Copy link

type Item = 'semlinker,lolo,kakuqo';

type Split<
	S extends string,
	Delimiter extends string,
> = S extends `${infer A}${Delimiter}${infer B}`
  ? [A, ...Split<B, Delimiter>]
  : [S];

type ElementType = Split<Item, ','>; // ["semlinker", "lolo", "kakuqo"

知识点: ts 映射类型里可以使用js里的模板变量的语法,用法和含义都相同
思路: 熟练掌握 extends 配合 infer的用法

@safarishi
Copy link

type ElementType3 = Split<'abcdef',

Split<'a,b,', ','> 这个期望结果是否符合预期

@Gengar-666
Copy link

type Split<
	S extends string, 
	Delimiter extends string,
> = S extends `${infer A}${Delimiter}${infer B}` ? [A, ...Split<B, Delimiter>] : [S]

type ElementType = Split<Item, ','>; // ["semlinker", "lolo", "kakuqo"]

@liulise
Copy link

liulise commented Dec 9, 2021

type Split<
S extends string,
Delimiter extends string,
> = S extends `${infer L}${Delimiter}${infer R}`
? [L, ...Split<R, Delimiter>]
: [S];

@pingan8787
Copy link

pingan8787 commented Dec 9, 2021 via email

@zhangchuachua
Copy link

zhangchuachua commented Feb 24, 2022

type Split<S extends string, Delimiter extends string> = S extends `${infer Key}${Delimiter}${infer Rest}`
  ? [Key, ...Split3<Rest, Delimiter>]
  : S extends ''
    ? Delimiter extends ''
      ? []
      : [S]
    : [S];

type A3 = Split3<'', ''> // []
type B3 = Split3<'o', ''> // ['o']
type C3 = Split3<'o', 'o'> // ['','']

@zouyk
Copy link

zouyk commented Mar 7, 2022

const strDome = 'semlinker,lolo,kakuqo,ahhah'
type Item = typeof strDome;

type Split<
S extends string,
Delimiter extends string,
> = S extends ${infer A},${infer B} ? [A, ...Split<B, Delimiter>] : [S]

type ElementType = Split<Item, ','>; // ["semlinker", "lolo", "kakuqo"]

const reuslt: Split<Item, ','> = String.prototype.split.call(strDome, ',')

@waleiwalei
Copy link

waleiwalei commented Mar 21, 2022

type Item = 'semlinker,lolo,kakuqo';

type ElementType = Split<Item, ','>; // ["semlinker", "lolo", "kakuqo"]

type Split<
	S extends string, 
	Delimiter extends string,
> = 
  S extends `${infer Left}${Delimiter}${infer Right}`
    ? [Left, ...Split<Right, Delimiter>]
    : [S]
type Split<
	S extends string, 
	Delimiter extends string,
  Arr extends string[] = []
> = 
  S extends `${infer Left}${Delimiter}${infer Right}`
    ? Split<Right, Delimiter, [...Arr, Left]>
    : [...Arr, S]

@hezhisheng1930
Copy link

type Split<
S extends string,
Delimiter extends string,
TEMP extends string[] = []
> = S extends ${infer First}${Delimiter}${infer Rest}
? Split<Rest, Delimiter, [...TEMP, First]>
: S extends ''
? TEMP : [...TEMP, S]

@zhixiaotong
Copy link

type Split<
	S extends string, 
	Delimiter extends string,
> = S extends `${infer A}${Delimiter}${infer B}` ? [A, ...Split<B, Delimiter>] : [S]

@SweeperDuan
Copy link

type Split<
	S extends string, 
	Delimiter extends string,
> = S extends `${infer A}${Delimiter}${infer Rest}`
  ? [A, ...Split<Rest, Delimiter>]
  : [S];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests