TypeScript

😊 ts中的访问修饰符

  • public,任何地方
  • private,只能在类的内部访问
  • protected,能在类的内部访问和子类中访问
  • readonly,属性设置为只读

    😊 constreadonly的区别

  1. const用于变量,readonly用于属性
  2. const在运行时检查,readonly在编译时检查
  3. 使用const变量保存的数组,可以使用pushpop等方法。但是如果使用ReadonlyArray<number>声明的数组不能使用pushpop等方法。

    😊 枚举和常量枚举(const枚举)的区别

  4. 枚举会被编译时会编译成一个对象,可以被当作对象使用

  5. const枚举会在ts编译期间被删除,避免额外的性能开销
    1. // 普通枚举
    2. enum Witcher {
    3. Ciri = 'Queen',
    4. Geralt = 'Geralt of Rivia'
    5. }
    6. function getGeraltMessage(arg: {[key: string]: string}): string {
    7. return arg.Geralt
    8. }
    9. getGeraltMessage(Witcher) // Geralt of Rivia
    1. // const枚举
    2. const enum Witcher {
    3. Ciri = 'Queen',
    4. Geralt = 'Geralt of Rivia'
    5. }
    6. const witchers: Witcher[] = [Witcher.Ciri, Witcher.Geralt]
    7. // 编译后
    8. // const witchers = ['Queen', 'Geralt of Rivia'

    😊 ts中interface可以给Function/Array/Class做声明吗?

    1. // 函数类型
    2. interface SearchFunc {
    3. (source: string, subString: string): boolean;
    4. }
    5. let mySearch: SearchFunc;
    6. mySearch = function(source: string, subString: string) {
    7. let result = source.search(subString);
    8. return result > -1;
    9. }
    ```typescript // Array interface StringArray {

}

let myArray: StringArray; myArray = [“Bob”, “Fred”];

  1. ```typescript
  2. // Class, constructor存在于类的静态部分,所以不会检查
  3. interface ClockInterface {
  4. currentTime: Date;
  5. setTime(d: Date);
  6. }
  7. class Clock implements ClockInterface {
  8. currentTime: Date;
  9. setTime(d: Date) {
  10. this.currentTime = d;
  11. }
  12. constructor(h: number, m: number) { }
  13. }

ts中的this和js中的this有什么差异?

不了解

😊 ts中如何枚举联合类型的key?

  1. type Name = { name: string }
  2. type Age = { age: number }
  3. type Union = Name | Age
  4. type UnionKey<P> = P extends infer P ? keyof P : never
  5. type T = UnionKey<Union>

😊 ts中 ?.??!._** 等符号的含义?

  • ?. 可选链
  • ?? ?? 类似与短路或,??避免了一些意外情况0,NaN以及””,false被视为false值。只有undefind,null被视为false值。
  • !. 在变量名后添加!,可以断言排除undefinednull类型
  • _ , 声明该函数将被传递一个参数,但您并不关心它
  • ** 求幂
  • !:,待会分配这个变量,ts不要担心 ```typescript // ?? let x = foo ?? bar(); // 等价于 let x = foo !== null && foo !== undefined ? foo : bar();

// !. let a: string | null | undefined a.length // error a!.length // ok

  1. <a name="HVae4"></a>
  2. ## 😊 什么是抗变、双变、协变和逆变?
  3. - Covariant 协变,TS对象兼容性是协变,父类 <= 子类,是可以的。子类 <= 父类,错误。
  4. - Contravariant 逆变,禁用`strictFunctionTypes`编译,函数参数类型是逆变的,父类 <= 子类,是错误。子类 <= 父类,是可以的。
  5. - Bivariant 双向协变,函数参数的类型默认是双向协变的。父类 <= 子类,是可以的。子类 <= 父类,是可以的。
  6. <a name="L0aR2"></a>
  7. ## 😊 ts中同名的interface或者同名的interface和class可以合并吗?
  8. 1. `interface`会合并
  9. 1. `class`不可以合并
  10. <a name="TLwji"></a>
  11. ## 😊 如何使ts项目引入并识别编译为js的npm库包?
  12. 1. `npm install @types/xxxx`
  13. 1. 自己添加描述文件
  14. <a name="WQjhj"></a>
  15. ## 😊 ts如何自动生成库包的声明文件?
  16. 可以配置tsconfig.json文件中的`declaration`和`outDir`
  17. 1. `declaration: true`, 将会自动生成声明文件
  18. 1. `outDir: ''`, 指定目录
  19. <a name="IYwuk"></a>
  20. ## 😊 什么是泛型
  21. 泛型用来来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。简单的说,“泛型就是把类型当成参数”。
  22. <a name="vroOy"></a>
  23. ## 😊 `-?`,`-readonly` 是什么含义
  24. 用于删除修饰符
  25. ```typescript
  26. type A = {
  27. a: string;
  28. b: number;
  29. }
  30. type B = {
  31. [K in keyof A]?: A[K]
  32. }
  33. type C = {
  34. [K in keyof B]-?: B[K]
  35. }
  36. type D = {
  37. readonly [K in keyof A]: A[K]
  38. }
  39. type E = {
  40. -readonly [K in keyof A]: A[K]
  41. }

😊 TS是基于结构类型兼容

typescript的类型兼容是基于结构的,不是基于名义的。下面的代码在ts中是完全可以的,但在java等基于名义的语言则会抛错。

  1. interface Named { name: string }
  2. class Person {
  3. name: string
  4. }
  5. let p: Named
  6. // ok
  7. p = new Person()

😊 const断言

const断言,typescript会为变量添加一个自身的字面量类型

  1. 对象字面量的属性,获得readonly的属性,成为只读属性
  2. 数组字面量成为readonly tuple只读元组
  3. 字面量类型不能被扩展(比如从hello类型到string类型)

    1. // type '"hello"'
    2. let x = "hello" as const
    3. // type 'readonly [10, 20]'
    4. let y = [10, 20] as const
    5. // type '{ readonly text: "hello" }'
    6. let z = { text: "hello" } as const

    😊 typeinterface 的区别

  4. 类型别名可以为任何类型引入名称。例如基本类型,联合类型等

  5. 类型别名不支持继承
  6. 类型别名不会创建一个真正的名字
  7. 类型别名无法被实现(implements),而接口可以被派生类实现
  8. 类型别名重名时编译器会抛出错误,接口重名时会产生合并

    😊 implementsextends 的区别

  • extends, 子类会继承父类的所有属性和方法。
  • implements,使用implements关键字的类将需要实现需要实现的类的所有属性和方法。

    😊 枚举和 object 的区别

  1. 枚举可以通过枚举的名称,获取枚举的值。也可以通过枚举的值获取枚举的名称。
  2. object只能通过key获取value
  3. 数字枚举在不指定初始值的情况下,枚举值会从0开始递增。
  4. 虽然在运行时,枚举是一个真实存在的对象。但是使用keyof时的行为却和普通对象不一致。必须使用keyof typeof才可以获取枚举所有属性名。

    😊 never, void 的区别

  • nevernever表示永远不存在的类型。比如一个函数总是抛出错误,而没有返回值。或者一个函数内部有死循环,永远不会有返回值。函数的返回值就是never类型。
  • void,没有显示的返回值的函数返回值为void类型。如果一个变量为void类型,只能赋予undefined或者null

    unknown, any的区别

    unknown类型和any类型类似。与any类型不同的是。unknown类型可以接受任意类型赋值,但是unknown类型赋值给其他类型前,必须被断言

    😊 如何在 window 扩展类型

    1. declare global {
    2. interface Window {
    3. myCustomFn: () => void;
    4. }
    5. }

    复杂的类型推导题目

    🤔 implement UnionToIntersection

    ```typescript type A = UnionToIntersection<{a: string} | {b: string} | {c: string}> // {a: string} & {b: string} & {c: string}

// 实现UnionToIntersection type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never // https://stackoverflow.com/questions/50374908/transform-union-type-to-intersection-type // https://jkchao.github.io/typescript-book-chinese/tips/infer.html#%E4%B8%80%E4%BA%9B%E7%94%A8%E4%BE%8B

  1. <a name="slNAA"></a>
  2. ### 😊 `implement ToNumber`
  3. ```typescript
  4. type A = ToNumber<'1'> // 1
  5. type B = ToNumber<'40'> // 40
  6. type C = ToNumber<'0'> // 0
  7. // 实现ToNumber
  8. type ToNumber<T extends string, R extends any[] = []> =
  9. T extends `${R['length']}` ? R['length'] : ToNumber<T, [1, ...R]>;

😊 implement Add<A, B>

  1. type A = Add<1, 2> // 3
  2. type B = Add<0, 0> // 0
  3. // 实现ADD
  4. type NumberToArray<T, R extends any[]> = T extends R['length'] ? R : NumberToArray<T, [1, ...R]>
  5. type Add<T, R> = [...NumberToArray<T, []>, ...NumberToArray<R, []>]['length']

😊 implement SmallerThan<A, B>

  1. type A = SmallerThan<0, 1> // true
  2. type B = SmallerThan<1, 0> // false
  3. type C = SmallerThan<10, 9> // false
  4. // 实现SmallerThan
  5. type SmallerThan<N extends number, M extends number, L extends any[] = [], R extends any[] = []> =
  6. N extends L['length'] ?
  7. M extends R['length'] ? false : true
  8. :
  9. M extends R['length'] ? false : SmallerThan<N, M, [1, ...L], [1, ...R]>;

😊 implement LargerThan<A, B>

  1. type A = LargerThan<0, 1> // false
  2. type B = LargerThan<1, 0> // true
  3. type C = LargerThan<10, 9> // true
  4. // 实现LargerThan
  5. type LargerThan<N extends number, M extends number, L extends any[] = [], R extends any[] = []> =
  6. N extends L['length'] ?
  7. false : M extends R['length'] ?
  8. true : LargerThan<N, M, [1, ...L], [1, ...R]>;

😊 implement IsAny

  1. type A = IsAny<string> // false
  2. type B = IsAny<any> // true
  3. type C = IsAny<unknown> // false
  4. type D = IsAny<never> // false
  5. // 实现IsAny
  6. type IsAny<T> = true extends (T extends never ? true : false) ?
  7. false extends (T extends never ? true : false) ?
  8. true
  9. :
  10. false
  11. :
  12. false;
  13. // 更简单的实现
  14. type IsAny<T> = 0 extends (T & 1) ? true : false;

😊 implement Filter<T, A>

  1. type A = Filter<[1,'BFE', 2, true, 'dev'], number> // [1, 2]
  2. type B = Filter<[1,'BFE', 2, true, 'dev'], string> // ['BFE', 'dev']
  3. type C = Filter<[1,'BFE', 2, any, 'dev'], string> // ['BFE', any, 'dev']
  4. // 实现Filter
  5. type Filter<T extends any[], A, N extends any[] = []> =
  6. T extends [infer P, ...infer Q] ?
  7. 0 extends (P & 1) ? Filter<Q, A, [...N, P]> :
  8. P extends A ? Filter<Q, A, [...N, P]> : Filter<Q, A, N>
  9. : N;

😊 implement TupleToString

  1. type A = TupleToString<['a']> // 'a'
  2. type B = TupleToString<['B', 'F', 'E']> // 'BFE'
  3. type C = TupleToString<[]> // ''
  4. // 实现TupleToString
  5. type TupleToString<T extends any[], S extends string = '', A extends any[] = []> =
  6. A['length'] extends T['length'] ? S : TupleToString<T, `${S}${T[A['length']]}`, [1, ...A]>

😊 implement RepeatString<T, C>

  1. type A = RepeatString<'a', 3> // 'aaa'
  2. type B = RepeatString<'a', 0> // ''
  3. // 实现RepeatString
  4. type RepeatString<T extends string, C extends number, S extends string = '', A extends any[] = []> =
  5. A['length'] extends C ? S : RepeatString<T, C, `${T}${S}`, [1, ...A]>

😊 implement Push<T, I>

  1. type A = Push<[1,2,3], 4> // [1,2,3,4]
  2. type B = Push<[1], 2> // [1, 2]
  3. type C = Push<[], string> // [string]
  4. // 实现Push
  5. type Push<T extends any[], I> = T extends [...infer P] ? [...P, I] : [I]

😊 implement Flat

  1. type A = Flat<[1,2,3]> // [1,2,3]
  2. type B = Flat<[1,[2,3], [4,[5,[6]]]]> // [1,2,3,4,5,6]
  3. type C = Flat<[]> // []
  4. // 实现Flat
  5. type Flat<T extends any[]> =
  6. T extends [infer P, ...infer Q] ?
  7. P extends any[] ? [...Flat<P>, ...Flat<Q>] : [P, ...Flat<Q>]
  8. : [];

😊 implement Shift

  1. type A = Shift<[1,2,3]> // [2,3]
  2. type B = Shift<[1]> // []
  3. type C = Shift<[]> // []
  4. // 实现Shift
  5. type Shift<T extends any[]> = T extends [infer P, ...infer Q] ? [...Q] : [];

😊 implement Repeat<T, C>

  1. type A = Repeat<number, 3> // [number, number, number]
  2. type B = Repeat<string, 2> // [string, string]
  3. type C = Repeat<1, 1> // [1, 1]
  4. type D = Repeat<0, 0> // []
  5. // 实现Repeat
  6. type Repeat<T, C, R extends any[] = []> =
  7. R['length'] extends C ? R : Repeat<T, C, [...R, T]>

😊 implement ReverseTuple

  1. type A = ReverseTuple<[string, number, boolean]> // [boolean, number, string]
  2. type B = ReverseTuple<[1,2,3]> // [3,2,1]
  3. type C = ReverseTuple<[]> // []
  4. // 实现ReverseTuple
  5. type ReverseTuple<T extends any[], A extends any[] = []> =
  6. T extends [...infer Q, infer P] ?
  7. A['length'] extends T['length'] ? A : ReverseTuple<Q, [...A, P]>
  8. : A;

😊 implement UnwrapPromise

  1. type A = UnwrapPromise<Promise<string>> // string
  2. type B = UnwrapPromise<Promise<null>> // null
  3. type C = UnwrapPromise<null> // Error
  4. // 实现UnwrapPromise
  5. type UnwrapPromise<T> = T extends Promise<infer P> ? P : Error;

😊 implement LengthOfString

  1. type A = LengthOfString<'BFE.dev'> // 7
  2. type B = LengthOfString<''> // 0
  3. // 实现LengthOfString
  4. type LengthOfString<T extends string, A extends any[] = []> =
  5. T extends `${infer P}${infer Q}` ? LengthOfString<Q, [1, ...A]> : A['length']

😊 implement StringToTuple

  1. type A = StringToTuple<'BFE.dev'> // ['B', 'F', 'E', '.', 'd', 'e','v']
  2. type B = StringToTuple<''> // []
  3. // 实现
  4. type StringToTuple<T extends string, A extends any[] = []> =
  5. T extends `${infer K}${infer P}` ? StringToTuple<P, [...A, K]> : A;

😊 implement LengthOfTuple

  1. type A = LengthOfTuple<['B', 'F', 'E']> // 3
  2. type B = LengthOfTuple<[]> // 0
  3. // 实现
  4. type LengthOfTuple<T extends any[], R extends any[] = []> =
  5. R['length'] extends T['length'] ? R['length'] : LengthOfTuple<T, [...R, 1]>

😊 implement LastItem

  1. type A = LastItem<[string, number, boolean]> // boolean
  2. type B = LastItem<['B', 'F', 'E']> // 'E'
  3. type C = LastItem<[]> // never
  4. // 实现LastItem
  5. type LastItem<T> = T extends [...infer P, infer Q] ? Q : never;

😊 implement FirstItem

  1. type A = FirstItem<[string, number, boolean]> // string
  2. type B = FirstItem<['B', 'F', 'E']> // 'B'
  3. // 实现FirstItem
  4. type FirstItem<T> = T extends [infer P, ...infer Q] ? P : never;

😊 implement FirstChar

  1. type A = FirstChar<'BFE'> // 'B'
  2. type B = FirstChar<'dev'> // 'd'
  3. type C = FirstChar<''> // never
  4. // 实现FirstChar
  5. type FirstChar<T> = T extends `${infer P}${infer Q}` ? P : never;

😊 implement Pick<T, K>

  1. type Foo = {
  2. a: string
  3. b: number
  4. c: boolean
  5. }
  6. type A = MyPick<Foo, 'a' | 'b'> // {a: string, b: number}
  7. type B = MyPick<Foo, 'c'> // {c: boolean}
  8. type C = MyPick<Foo, 'd'> // Error
  9. // 实现MyPick<T, K>
  10. type MyPick<T, K extends keyof T> = {
  11. [Key in K]: T[Key]
  12. }

😊 implement Readonly

  1. type Foo = {
  2. a: string
  3. }
  4. const a:Foo = {
  5. a: 'BFE.dev',
  6. }
  7. a.a = 'bigfrontend.dev'
  8. // OK
  9. const b:MyReadonly<Foo> = {
  10. a: 'BFE.dev'
  11. }
  12. b.a = 'bigfrontend.dev'
  13. // Error
  14. // 实现MyReadonly
  15. type MyReadonly<T> = {
  16. readonly [K in keyof T]: T[K]
  17. }

😊 implement Record<K, V>

  1. type Key = 'a' | 'b' | 'c'
  2. const a: Record<Key, string> = {
  3. a: 'BFE.dev',
  4. b: 'BFE.dev',
  5. c: 'BFE.dev'
  6. }
  7. a.a = 'bigfrontend.dev' // OK
  8. a.b = 123 // Error
  9. a.d = 'BFE.dev' // Error
  10. type Foo = MyRecord<{a: string}, string> // Error
  11. // 实现MyRecord
  12. type MyRecord<K extends number | string | symbol, V> = {
  13. [Key in K]: V
  14. }

🤔️ implement Exclude

  1. type Foo = 'a' | 'b' | 'c'
  2. type A = MyExclude<Foo, 'a'> // 'b' | 'c'
  3. type B = MyExclude<Foo, 'c'> // 'a' | 'b
  4. type C = MyExclude<Foo, 'c' | 'd'> // 'a' | 'b'
  5. type D = MyExclude<Foo, 'a' | 'b' | 'c'> // never
  6. // 实现 MyExclude<T, K>
  7. type MyExclude<T, K> = T extends K ? never : T;

🤔️ implement Extract<T, U>

  1. type Foo = 'a' | 'b' | 'c'
  2. type A = MyExtract<Foo, 'a'> // 'a'
  3. type B = MyExtract<Foo, 'a' | 'b'> // 'a' | 'b'
  4. type C = MyExtract<Foo, 'b' | 'c' | 'd' | 'e'> // 'b' | 'c'
  5. type D = MyExtract<Foo, never> // never
  6. // 实现MyExtract<T, U>
  7. type MyExtract<T, U> = T extends U ? T : never

😊 implement Omit<T, K>

  1. type Foo = {
  2. a: string
  3. b: number
  4. c: boolean
  5. }
  6. type A = MyOmit<Foo, 'a' | 'b'> // {c: boolean}
  7. type B = MyOmit<Foo, 'c'> // {a: string, b: number}
  8. type C = MyOmit<Foo, 'c' | 'd'> // {a: string, b: number}
  9. // 实现MyOmit
  10. type MyOmit<T, K extends number | string | symbol> = {
  11. [Key in Exclude<keyof T, K>]: T[Key]
  12. }
  13. type MyOmit<T, K extends number | string | symbol> = Pick<T, Exclude<keyof T, K>>

😊 implement NonNullable

  1. type Foo = 'a' | 'b' | null | undefined
  2. type A = MyNonNullable<Foo> // 'a' | 'b'
  3. // 实现NonNullable
  4. type MyNonNullable<T> = T extends null | undefined ? never : T;

😊 implement Parameters

  1. type Foo = (a: string, b: number, c: boolean) => string
  2. type A = MyParameters<Foo> // [a:string, b: number, c:boolean]
  3. type B = A[0] // string
  4. type C = MyParameters<{a: string}> // Error
  5. // 实现MyParameters<T>
  6. type MyParameters<T extends (...params: any[]) => any> =
  7. T extends (...params: [...infer P]) => any ? P : never

😊 implement ConstructorParameters

  1. class Foo {
  2. constructor (a: string, b: number, c: boolean) {}
  3. }
  4. type C = MyConstructorParameters<typeof Foo>
  5. // [a: string, b: number, c: boolean]
  6. // 实现MyConstructorParameters<T>
  7. type MyConstructorParameters<T extends new (...params: any[]) => any> =
  8. T extends new (...params: [...infer P]) => any ? P : never

😊 implement ReturnType

  1. type Foo = () => {a: string}
  2. type A = MyReturnType<Foo> // {a: string}
  3. // 实现MyReturnType<T>
  4. type MyReturnType<T extends (...params: any[]) => any> =
  5. T extends (...params: any[]) => infer P ? P : never;

😊 implement InstanceType

  1. class Foo {}
  2. type A = MyInstanceType<typeof Foo> // Foo
  3. type B = MyInstanceType<() => string> // Error
  4. // 实现MyInstanceType<T>
  5. type MyInstanceType<T extends new (...params: any[]) => any> =
  6. T extends new (...params: any[]) => infer P ? P : never;

😊 implement ThisParameterType

  1. function Foo(this: {a: string}) {}
  2. function Bar() {}
  3. type A = MyThisParameterType<typeof Foo> // {a: string}
  4. type B = MyThisParameterType<typeof Bar> // unknown
  5. // 实现MyThisParameterType<T>
  6. type MyThisParameterType<T extends (this: any, ...params: any[]) => any> =
  7. T extends (this: infer P, ...params: any[]) => any ? P : unknown;

😊 implement TupleToUnion

  1. type Foo = [string, number, boolean]
  2. type Bar = TupleToUnion<Foo> // string | number | boolean
  3. // 实现TupleToUnion<T>
  4. type TupleToUnion<T extends any[], R = T[0]> =
  5. T extends [infer P, ...infer Q] ? TupleToUnion<Q, R | P> : R;
  6. // 其他回答
  7. type TupleToUnion<T extends any[]> = T[number]

😊 implement Partial

  1. type Foo = {
  2. a: string
  3. b: number
  4. c: boolean
  5. }
  6. // below are all valid
  7. const a: MyPartial<Foo> = {}
  8. const b: MyPartial<Foo> = {
  9. a: 'BFE.dev'
  10. }
  11. const c: MyPartial<Foo> = {
  12. b: 123
  13. }
  14. const d: MyPartial<Foo> = {
  15. b: 123,
  16. c: true
  17. }
  18. const e: MyPartial<Foo> = {
  19. a: 'BFE.dev',
  20. b: 123,
  21. c: true
  22. }
  23. // 实现MyPartial<T>
  24. type MyPartial<T> = {
  25. [K in keyof T]?: T[K]
  26. }

😊 Required

  1. // all properties are optional
  2. type Foo = {
  3. a?: string
  4. b?: number
  5. c?: boolean
  6. }
  7. const a: MyRequired<Foo> = {}
  8. // Error
  9. const b: MyRequired<Foo> = {
  10. a: 'BFE.dev'
  11. }
  12. // Error
  13. const c: MyRequired<Foo> = {
  14. b: 123
  15. }
  16. // Error
  17. const d: MyRequired<Foo> = {
  18. b: 123,
  19. c: true
  20. }
  21. // Error
  22. const e: MyRequired<Foo> = {
  23. a: 'BFE.dev',
  24. b: 123,
  25. c: true
  26. }
  27. // valid
  28. // 实现MyRequired<T>
  29. type MyRequired<T> = {
  30. [K in keyof T]-?: T[K]
  31. }

😊 implement LastChar

  1. type A = LastChar<'BFE'> // 'E'
  2. type B = LastChar<'dev'> // 'v'
  3. type C = LastChar<''> // never
  4. // 实现FirstChar<T>
  5. type LastChar<T extends string, A extends string[] = []> =
  6. T extends `${infer P}${infer Q}` ? LastChar<Q, [...A, P]> :
  7. A extends [...infer L, infer R] ? R : never
  8. ;

😊 implement IsNever

  1. // https://stackoverflow.com/questions/53984650/typescript-never-type-inconsistently-matched-in-conditional-type
  2. // https://www.typescriptlang.org/docs/handbook/advanced-types.html#v
  3. type A = IsNever<never> // true
  4. type B = IsNever<string> // false
  5. type C = IsNever<undefined> // false
  6. // 实现IsNever<T>
  7. type IsNever<T> = [T] extends [never] ? true : false;

😊 implement KeysToUnion

  1. type A = KeyToUnion<{
  2. a: string;
  3. b: number;
  4. c: symbol;
  5. }>
  6. // 'a' | 'b' | 'c'
  7. // 实现KeyToUnion
  8. type KeyToUnion<T> = {
  9. [K in keyof T]: K;
  10. }[keyof T]

😊 implement ValuesToUnion

  1. type A = ValuesToUnion<{
  2. a: string;
  3. b: number;
  4. c: symbol;
  5. }>
  6. // string | number | symbol
  7. // ValuesToUnion
  8. type ValuesToUnion<T> = T[keyof T]

FindIndex<T, E>

  1. type IsAny<T> = 0 extends (T & 1) ? true : false;
  2. type IsNever<T> = [T] extends [never] ? true : false;
  3. type TwoAny<A, B> = IsAny<A> extends IsAny<B> ? IsAny<A> : false;
  4. type TwoNever<A, B> = IsNever<A> extends IsNever<B> ? IsNever<A> : false;
  5. type SingleAny<A, B> = IsAny<A> extends true ? true : IsAny<B>
  6. type SingleNever<A, B> = IsNever<A> extends true ? true : IsNever<B>
  7. type FindIndex<T extends any[], E, A extends any[] = []> =
  8. T extends [infer P, ...infer Q] ?
  9. TwoAny<P, E> extends true ?
  10. A['length']
  11. :
  12. TwoNever<P, E> extends true ?
  13. A['length']
  14. :
  15. SingleAny<P, E> extends true ?
  16. FindIndex<Q, E, [1, ...A]>
  17. :
  18. SingleNever<P, E> extends true ?
  19. FindIndex<Q, E, [1, ...A]>
  20. :
  21. P extends E ? A['length'] : FindIndex<Q, E, [1, ...A]>
  22. :
  23. never

implement Trim

  1. type A = Trim<' BFE.dev'> // 'BFE'
  2. type B = Trim<' BFE. dev '> // 'BFE. dev'
  3. type C = Trim<' BFE . dev '> // 'BFE . dev'
  4. type StringToTuple<T extends string, A extends any[] = []> =
  5. T extends `${infer K}${infer P}` ? StringToTuple<P, [...A, K]> : A;
  6. type TupleToString<T extends any[], S extends string = '', A extends any[] = []> =
  7. A['length'] extends T['length'] ? S : TupleToString<T, `${S}${T[A['length']]}`, [1, ...A]>
  8. type Trim<T extends string, A extends any[] = StringToTuple<T>> =
  9. A extends [infer P, ...infer Q] ?
  10. P extends ' ' ?
  11. Trim<T, Q>
  12. :
  13. A extends [...infer M, infer N] ?
  14. N extends ' ' ?
  15. Trim<T, M>
  16. :
  17. TupleToString<A>
  18. :
  19. ''
  20. :
  21. '';

还有更多 UnionToTuple, IntersectionToUnion?