Coder Social home page Coder Social logo

Comments (39)

semlinker avatar semlinker commented on May 13, 2024 18

6.1 NativeFlat

type NaiveFlat<T extends any[]> = {
  [P in keyof T]: T[P] extends any[] ? T[P][number] : T[P]
}[number]

type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult的结果: "a" | "b" | "c" | "d"

6.2 DeepFlat

type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]];

type DeepFlat<T extends any[]> = {
  [K in keyof T]: T[K] extends any[] ? DeepFlat<T[K]> : T[K]
}[number]

type DeepTestResult = DeepFlat<Deep>
// DeepTestResult: "a" | "b" | "c" | "d" | "e"

from awesome-typescript.

jrs64 avatar jrs64 commented on May 13, 2024 16
type NaiveFlat<T extends any[]> = T extends (infer P)[] ? P extends any[] ? NaiveFlat<P> : P : never;
// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>;
type DeepResult = NaiveFlat<[['a'], ['b', 'c'], [['d']], [[[['e']]]]]>;

递归写法

from awesome-typescript.

dolphin0618 avatar dolphin0618 commented on May 13, 2024 8

["Q","W"][number] {0:"Q",1:"W",}[number]这种格式为什么会自动循环展开取值啊,学TS的时候好像没看到这种写法啊

["Q","W"][0] // Q
["Q","W"][1 | 2]  // Q | W
//  1 | 2 extends number
["Q","W"][number]  // Q | W

from awesome-typescript.

ChangerHe avatar ChangerHe commented on May 13, 2024 5
// 解法1: 最佳解法, 通过inter来推断一个P类型
// 如果P类型扩展与any[], 也就证明它是数组, 这个时候递归来执行NaiveFlat
// 否则, 直接返回此类型
// 如果T不扩展于 any[] (这里是(infer P)[], 额外加了个类型的推断) 则为never
type NaiveFlat<T extends any[]> = T extends (infer P)[] ? P extends any[] ? NaiveFlat<P> : P : never

// 解法2
// 解法2之前, 我们先了解一个前置知识, 如何提取数组的值, 作为类型
type TypeD = ['a', 'b']
// 这里的原因是: 使用[number]相当于提取了所有的数组下标, 通过数组下标则可以取到所有的数组值了
type TypeKeyD = TypeD[number] // 'a' | 'b'
// 因此, 解法2到这里就非常简单了, 只需要判断一下, 如果是数组, 则继续往下递归执行, 否则返回该值即可
type NaiveFlat1<T extends any[]> = {
  [P in keyof T]: T[P] extends any[] ? NaiveFlat1<T[P]> : T[P]
}[number]

from awesome-typescript.

zjxxxxxxxxx avatar zjxxxxxxxxx commented on May 13, 2024 3

一个月能告诉我一下,这里的 [number] 是什么用的吗?完全找不到文档呀

[number] 用来代指所有数组下标,不管下标 0 还是下标 1,它们都是 number 型。
[''a,'b'][number] === ['a','b'][0|1] === 'a'|'b'

from awesome-typescript.

zhaoxiongfei avatar zhaoxiongfei commented on May 13, 2024 2
// 定义一个 NativeFlat 工具类型,支持把数组类型拍平(扁平化)。具体的使用示例如下所示:
type NaiveFlat<T extends any[]> = T extends [infer A, ...infer B]
 ? A extends any[]
  ? NaiveFlat<A> | NaiveFlat<B>
  : A | NaiveFlat<B>
 : never;

// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult的结果: "a" | "b" | "c" | "d"
// 在完成 NaiveFlat 工具类型之后,在继续实现 DeepFlat 工具类型,以支持多维数组类型:

// 测试用例
type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]]
type DeepTestResult = NaiveFlat<Deep>
// DeepTestResult: "a" | "b" | "c" | "d" | "e"

这个题对我来说难度是只有一级的那个扁平化,我这里实现完成后自动就是deep的。
这里使用的知识点也就是 extends 配合 infer 来提取,之后递归的去做。

from awesome-typescript.

dolphin0618 avatar dolphin0618 commented on May 13, 2024 2

如果固定双层数组的话,用这个试试

type NaiveFlat<T extends any[]> = T[number][number]

多层实现方法,适用任意层级,同样可以替换上面的NaiveFlat

type DeepFlat<T> = T extends any[] ? DeepFlat<T[number]> : T

ts@ 4.2.3

from awesome-typescript.

douhaoi avatar douhaoi commented on May 13, 2024 1

目前针对元组内都是一维数组的情况下能够成立,但是如果是多层级的话就不行。比较有局限性。希望宝哥帮忙看一下这种方式是否能够做到通用性。

  • 第一种:
type NaiveFlat<T extends any[]> = T[number] extends any[] ? T[number][number] : T[number]

// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]> // 'a' | 'b' | 'c' | 'd'
  • 第二种:
type ArrayConcat<T extends any[]> = T extends [infer A, ...infer Rest] ?
    A extends any[] ? [...A, ...ArrayConcat<Rest>] : A : T;

type NativeFlat<T extends any[]> = ArrayConcat<T>[number]

type NativeResult = NativeFlat<[['a'], ['b', 'c'], ['d']]> //  'a' | 'b' | 'c' | 'd'

from awesome-typescript.

ccbabi avatar ccbabi commented on May 13, 2024 1

6.1 NativeFlat

type NaiveFlat<T extends any[]> = T[number] extends infer U // 你的实现代码
  ? U extends any[]
    ? U[number]
    : U
  : never;

// 测试用例:
type NaiveResult = NaiveFlat<[["a"], ["b", "c"], ["d"]]>;
// NaiveResult的结果: "a" | "b" | "c" | "d"

6.2 DeepFlat

type DeepFlat<T extends any[]> = T[number] extends infer U
  ? U extends any[]
    ? DeepFlat<U>
    : U
  : never;

// 测试用例
type Deep = [["a"], ["b", "c"], [["d"]], [[[["e"]]]]];
type DeepTestResult = DeepFlat<Deep>;
// DeepTestResult: "a" | "b" | "c" | "d" | "e"

from awesome-typescript.

githuandong avatar githuandong commented on May 13, 2024 1
type DeepFlat<T> = T extends Array<infer U> ? DeepFlat<U> : T;

// 测试用例:
type NaiveResult = DeepFlat<[["a"], [["b"], "c"], ["d"]]>;

from awesome-typescript.

zsqsmart avatar zsqsmart commented on May 13, 2024
type NaiveFlat<T extends any[]> = T[number] extends (infer P)[] ? P : T[number];
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>;
// NaiveResult的结果: "a" | "b" | "c" | "d"

type DeepFlat<T extends any[]> = T[number] extends (infer P)[] ? P extends any[] ? DeepFlat<P> : P : T[number];
type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]];
type DeepTestResult = DeepFlat<Deep>;
// DeepTestResult: "a" | "b" | "c" | "d" | "e"

from awesome-typescript.

xwnwho avatar xwnwho commented on May 13, 2024

6.1 NativeFlat

type NaiveFlat<T extends any[]> = {
  [P in keyof T]: T[P] extends any[] ? T[P][number] : T[P]
}[number]

type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult的结果: "a" | "b" | "c" | "d"

6.2 DeepFlat

type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]];

type DeepFlat<T extends any[]> = {
  [K in keyof T]: T[K] extends any[] ? DeepFlat<T[K]> : T[K]
}[number]

type DeepTestResult = DeepFlat<Deep>
// DeepTestResult: "a" | "b" | "c" | "d" | "e"

DeepFlat最后的[number]的写法有什么说法么?

from awesome-typescript.

winfa avatar winfa commented on May 13, 2024
type NaiveFlat<T extends any[]> = // 你的实现代码

// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult的结果: "a" | "b" | "c" | "d"
type NaiveFlat<T extends any[]> = T[number] extends { length: number } ? T[number][number] : T[number];

from awesome-typescript.

overQ-N avatar overQ-N commented on May 13, 2024
type NaiveFlat<T extends any[]> = T extends Array<infer P>
	? P extends any[]
		? NaiveFlat<P>
		: P
	: never

// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult的结果: "a" | "b" | "c" | "d"
type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]]
type DeepTestResult = NaiveFlat<Deep>
// DeepTestResult的结果: "a" | "b" | "c" | "d" | "e"

from awesome-typescript.

Mrlgm avatar Mrlgm commented on May 13, 2024
type NaiveFlat<T extends any[]> = {
  [P in keyof T]: T[P] extends any[] ? T[P][number] : T[P]
}[number]

type DeepFlat<T extends any[]> = {
  [P in keyof T]: T[P] extends any[] ? DeepFlat<T[P]> : T[P]
}[number]


// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult的结果: "a" | "b" | "c" | "d"

type DeepTestResult = DeepFlat<[['a'], ['b', ['c']], ['d']]>
// DeepTestResult的结果: "a" | "b" | "c" | "d"

from awesome-typescript.

duriann avatar duriann commented on May 13, 2024
type GetArrayEle<T> = {
  [k in keyof T & number]: T[k]
}[keyof T & number]
type TestGetArrayEle = GetArrayEle<[[number, boolean], [[string]]]>
type FlatArray<T> = T extends Array<infer p> ? p : T
type DeepFlatArray<T> = T extends Array<infer p> ? DeepFlatArray<p> : T

type TestFlatArray = FlatArray<TestGetArrayEle>
type TestDeepFlatArray = DeepFlatArray<[['a'], ['b', ['c']], ['d']]>

from awesome-typescript.

yang131323 avatar yang131323 commented on May 13, 2024

第六题

定义一个 NativeFlat 工具类型,支持把数组类型拍平(扁平化)。具体的使用示例如下所示:

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

// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult的结果: "a" | "b" | "c" | "d"

在完成 NaiveFlat 工具类型之后,在继续实现 DeepFlat 工具类型,以支持多维数组类型:

type DeepFlat<T extends any[]> = unknown // 你的实现代码

// 测试用例
type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]];
type DeepTestResult = DeepFlat<Deep>  
// DeepTestResult: "a" | "b" | "c" | "d" | "e"

请在下面评论你的答案

题目和示例感觉描述不一致,题目是要求将数组拍平,最终应该还是一个数组类型,但是示例展示的结果却是数组的常量联合类型,类型已经不是数组了,似乎编程获取数组值的类型

from awesome-typescript.

whatoeat2night avatar whatoeat2night commented on May 13, 2024

谁能告诉我一下,这里的 [number] 是做什么用的吗?完全找不到任何文档呀

from awesome-typescript.

rookiecdn avatar rookiecdn commented on May 13, 2024

[number] 到底是什么意思啊

from awesome-typescript.

yanglinxiao avatar yanglinxiao commented on May 13, 2024

type NaiveFlat<T extends any[]> = {
[K in keyof T]: T[K] extends any[] ? T[K][number] : T[K]
}[number]

// 测试用例:
type NaiveResult = NaiveFlat<[["a"], ["b", "c"], ["d"]]>;
// NaiveResult的结果: "a" | "b" | "c" | "d"

type DeepFlat<T extends any[]> = {
[K in keyof T]: T[K] extends any[] ? NaiveFlat<T[K]> : T[K]
}[number]

// 测试用例
type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]];
type DeepTestResult = DeepFlat

// 通用解法
// type NaiveFlat<T extends any[]> = T extends [infer A, ...infer B]
// ? A extends any[]
// ? NaiveFlat | NaiveFlat
// : A | NaiveFlat
// : never;

from awesome-typescript.

liulise avatar liulise commented on May 13, 2024

type NaiveFlat<T extends any[]> = T extends Array<infer R> ? (R extends any[] ? NaiveFlat<R> : R) : never;

from awesome-typescript.

changeling123xu avatar changeling123xu commented on May 13, 2024

为什么加[number],有大佬知道,踢我一下

from awesome-typescript.

hu0115 avatar hu0115 commented on May 13, 2024

["Q","W"][number] {0:"Q",1:"W",}[number]这种格式为什么会自动循环展开取值啊,学TS的时候好像没看到这种写法啊

from awesome-typescript.

wildes2021 avatar wildes2021 commented on May 13, 2024

为啥这样无法递归取到内部的type啊?
type DeepFlat<Arr extends any[]> = Arr[number] extends any[] ? DeepFlat<Arr[number]> : Arr[number];

from awesome-typescript.

ihoneys avatar ihoneys commented on May 13, 2024

["Q","W"][0 | 1] // Q | W

from awesome-typescript.

jeffacode avatar jeffacode commented on May 13, 2024
type DeepFlat<T extends any[]> = T extends Array<infer R> ? (R extends any[] ? DeepFlat<R> : R) : T
type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]]
type DeepTestResult = DeepFlat<Deep>

from awesome-typescript.

zjxxxxxxxxx avatar zjxxxxxxxxx commented on May 13, 2024
type NaiveFlat<T extends any[]> = T extends [infer F, ...infer R]
  ? (F extends unknown[] ? NaiveFlat<F> : F) | NaiveFlat<R>
  : T extends []
  ? never
  : T;

from awesome-typescript.

Bo-Teng avatar Bo-Teng commented on May 13, 2024

目前针对元组内都是一维数组的情况下能够成立,但是如果是多层级的话就不行。比较有局限性。希望宝哥帮忙看一下这种方式是否能够做到通用性。

  • 第一种:
type NaiveFlat<T extends any[]> = T[number] extends any[] ? T[number][number] : T[number]

// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]> // 'a' | 'b' | 'c' | 'd'
  • 第二种:
type ArrayConcat<T extends any[]> = T extends [infer A, ...infer Rest] ?
    A extends any[] ? [...A, ...ArrayConcat<Rest>] : A : T;

type NativeFlat<T extends any[]> = ArrayConcat<T>[number]

type NativeResult = NativeFlat<[['a'], ['b', 'c'], ['d']]> //  'a' | 'b' | 'c' | 'd'

可以 : type NaiveFlat<T extends any[]> =T[number] extends (infer P)[] ? P extends any[] ? NaiveFlat

: P : T[number]

from awesome-typescript.

shanbinbin avatar shanbinbin commented on May 13, 2024

为啥这样无法递归取到内部的type啊? type DeepFlat<Arr extends any[]> = Arr[number] extends any[] ? DeepFlat<Arr[number]> : Arr[number];

同问,为啥少包一层条件语句就不行了呢

from awesome-typescript.

YJCCreateAHistory avatar YJCCreateAHistory commented on May 13, 2024
type Flat<T extends any[]> = {
    // 递归调用
    [P in keyof T]: T[P] extends any[] ? DeepFlat<T[P]> : T[P] 
}

// 测试用例
type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]];
type DeepTestResult = Flat<Deep>  
type NaiveResult = Flat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult的结果: "a" | "b" | "c" | "d"
// DeepTestResult: "a" | "b" | "c" | "d" | "e"

from awesome-typescript.

chenweihan avatar chenweihan commented on May 13, 2024
type NaiveFlat<T extends any[]> = T[number] extends (infer P)[] ? P : T[number];
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>;
// NaiveResult的结果: "a" | "b" | "c" | "d"

@nilzhao 但是如果增加一个 'e'
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d'],'e']>
// 类型为: '["a"] | ["b", "c"] | ["d"] | "e"'. 而不是 "a" | "b" | "c" | "d" | "e"

总算看出问题,因为T是二维数组,T[number]代码T里的每个元素,而'e'是string,所以T[number]不能表示T中元素的所有类型,即不满足类型定义,全部都是false.

from awesome-typescript.

tiyunchen avatar tiyunchen commented on May 13, 2024

number 是什么虎狼用法?有相关文档吗?

from awesome-typescript.

itcast-e avatar itcast-e commented on May 13, 2024

关于T[number] 为什么可以这样用 在ts 索引类型访问中可以找到答案

from awesome-typescript.

MuLoo avatar MuLoo commented on May 13, 2024
// 二维拍平
type NaiveFlat<T extends any[]> = T[number] extends (infer P)[] ? P : T[number] 
// 深度拍平
type DeepFlat<T> = T extends (infer P)[] ? DeepFlat<P>  : T

// 测试
type AAA = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// "a" | "b" | "c" | "d"
type BBB = DeepFlat<[['a'], ['b', 'c'], ['d', ['e', 'f', ['G']]]]> 
//  "a" | "b" | "c" | "d" | "e" | "f" | "G"

from awesome-typescript.

yitjhy avatar yitjhy commented on May 13, 2024
// 递归
type DeepFlat<T extends unknown[]> = T extends [infer F, ...infer Rest]
  ? F extends unknown[]
    ? DeepFlat<F> | DeepFlat<Rest>
    : F | DeepFlat<Rest>
  : never
type DeepTestResult1 = DeepFlat<[['a', [[[['e']]]], 'be', 'fsdfg'], ['b', 'c'], ['d']]>
// "e" | "a" | "be" | "fsdfg" | "b" | "c" | "d"
type DeepTestResult2 = DeepFlat<[['a'], ['b', 'c'], [['d']], [[[['e']]]]]>
// "e" | "a" | "b" | "c" | "d"

from awesome-typescript.

MUTTERTOOLS avatar MUTTERTOOLS commented on May 13, 2024

对于第一种,上面的几种方法有些问题

type NaiveFlat<T extends any[]> = T[number] extends any[] ? T[number][number] : T[number];

// 当测试用例为元素类型全为数组类型的数组时,没有问题
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]> // 'a' | 'b' | 'c' | 'd'

// 但是当存在不为数组的元素时就出现了问题
type ErrorResult = NaiveFlat<[['a'], ['b', 'c'], ['d'], 'f']>	// ["a"] | ["b", "c"] | ["d"] | "f"

还有后面的另一种

type NaiveFlat<T extends any[]> = T[number] extends (infer P)[] ? P : T[number] 
// 使用上述两个测试用例
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]> // 'a' | 'b' | 'c' | 'd'
type ErrorResult = NaiveFlat<[['a'], ['b', 'c'], ['d'], 'f']>	// ["a"] | ["b", "c"] | ["d"] | "f"

TS的一些默认行为真是让人摸不着头脑啊

然后还有一个问题,对于第二种

type DeepFlat<Arr extends any[]> = Arr[number] extends any[] ? DeepFlat<Arr[number]> : Arr[number];
// 测试用例
type Deep = [ ['a'], ['b', 'c'], [['d']], [[[['e']]]], 'f'];
type DeepTestResult = DeepFlat<Deep>  // ["a"] | ["b", "c"] | "f" | [["d"]] | [[[["e"]]]]

这显然是一个比较符合直觉的递归写法,但是结果却不正确

所以我大胆猜测一手,是在条件判断语句内使用**Arr[number]**引起的!
浅浅的验证下
第一种:

type NaiveFlat<T extends any[], V = T[number]> = V extends any[] ? V[number] : V;

// 使用上述两个测试用例
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]> // 'a' | 'b' | 'c' | 'd'
type ErrorResult = NaiveFlat<[['a'], ['b', 'c'], ['d'], 'f']>	// "a" | "b" | "c" | "d" | "f"

第二种:

type DeepFlat<T extends any[], V = T[number]> = V extends any[] ? DeepFlat<V> : V;

// 测试用例
type Deep = [ ['a'], ['b', 'c'], [['d']], [[[['e']]]], 'f'];
type DeepTestResult = DeepFlat<Deep>  // "a" | "b" | "c" | "d" | "f" | "e"

虽然Arr[number]和泛型V都代表了联合类型,但执行结果却截然不同
有大佬弄清楚原理请记得踢我

from awesome-typescript.

shiyicyh avatar shiyicyh commented on May 13, 2024
// type NaiveFlat<T extends any[]> = {
// 	[K in keyof T]:T[K] extends any[]?T[K][number]:T[K]
// }
//上述类型测试用例结果为["a", "b" | "c", "d", "e"],所以需要加[number]展开

type NaiveFlat<T extends any[]> = {
	[K in keyof T]:T[K] extends any[]?T[K][number]:T[K]
}[number]

type DeepFlat<T extends any[]> = {
	[K in keyof T]:T[K] extends any[]?DeepFlat<T[K]>:T[K]
}[number]

// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d'],'e']>
//type NaiveResult = "a" | "b" | "c" | "d" | "e"

type DeepResult = DeepFlat<['a',['b','c'],['d'],[['e','f']],[[[['g']]]]]>
// type DeepResult = "a" | "b" | "c" | "d" | "e" | "f" | "g"

from awesome-typescript.

SweeperDuan avatar SweeperDuan commented on May 13, 2024
type NaiveFlat<T extends any[]> = {
  [K in keyof T]: T[K] extends any[] ? T[K][number] : T[K] 
}[number]

type DeepFlat<T extends any[]> = {
  [K in keyof T]: T[K] extends any[] ? DeepFlat<T[K]> : T[K] 
}[number]

from awesome-typescript.

Johnboy-max avatar Johnboy-max commented on May 13, 2024

type NaiveFlat = T extends Array ? NaiveFlat : T // 你的实现代码
// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>

// 测试用例
type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]]
type DeepTestResult = NaiveFlat

from awesome-typescript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.