1. TypeScript 相關(guān)問題(含解答)

        共 36242字,需瀏覽 73分鐘

         ·

        2021-08-03 14:52

        點擊上方 前端瓶子君,關(guān)注公眾號

        回復(fù)算法,加入前端編程面試算法每日一題群

        給出一大些面試題,然后不給答案。前端本來就卷,一些面試官看了文章后可能在自己都不知道答案的情況下,就跑去問面試者。我其實挺反感的這類文章的。

        ts基礎(chǔ)知識復(fù)習(xí)

        juejin.cn/post/684490…[1]

        ?? ts中的訪問修飾符

        • public,任何地方
        • private,只能在類的內(nèi)部訪問
        • protected,能在類的內(nèi)部訪問和子類中訪問
        • readonly,屬性設(shè)置為只讀

        ?? const和readonly的區(qū)別

        1. const用于變量,readonly用于屬性
        2. const在運行時檢查,readonly在編譯時檢查
        3. 使用const變量保存的數(shù)組,可以使用push,pop等方法。但是如果使用ReadonlyArray<number>聲明的數(shù)組不能使用push,pop等方法。

        ?? 枚舉和常量枚舉(const枚舉)的區(qū)別

        1. 枚舉會被編譯時會編譯成一個對象,可以被當(dāng)作對象使用
        2. const枚舉會在ts編譯期間被刪除,避免額外的性能開銷
        // 普通枚舉
        enum Witcher {
          Ciri = 'Queen',
          Geralt = 'Geralt of Rivia'
        }
        function getGeraltMessage(arg: {[key: string]: string}): string {
          return arg.Geralt
        }
        getGeraltMessage(Witcher) // Geralt of Rivia
        復(fù)制代碼
        // const枚舉
        const enum Witcher {
          Ciri = 'Queen',
          Geralt = 'Geralt of Rivia'
        }
        const witchers: Witcher[] = [Witcher.Ciri, Witcher.Geralt]
        // 編譯后
        // const witchers = ['Queen', 'Geralt of Rivia'
        復(fù)制代碼

        ?? ts中interface可以給Function/Array/Class做聲明嗎?

        // 函數(shù)類型
        interface SearchFunc {
          (source: string, subString: string): boolean;
        }
        let mySearch: SearchFunc;
        mySearch = function(source: string, subString: string{
          let result = source.search(subString);
          return result > -1;
        }
        復(fù)制代碼
        // Array
        interface StringArray {
          [index: number]: string;
        }

        let myArray: StringArray;
        myArray = ["Bob""Fred"];
        復(fù)制代碼
        // Class, constructor存在于類的靜態(tài)部分,所以不會檢查
        interface ClockInterface {
            currentTime: Date;
            setTime(d: Date);
        }

        class Clock implements ClockInterface {
            currentTime: Date;
            setTime(d: Date) {
                this.currentTime = d;
            }
            constructor(h: number, m: number) { }
        }
        復(fù)制代碼

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

        不了解

        ?? ts中如何枚舉聯(lián)合類型的key?

        type Name = { name: string }
        type Age = { age: number }
        type Union = Name | Age

        type UnionKey<P> = P extends infer P ? keyof P : never

        type T = UnionKey<Union>
        復(fù)制代碼

        ?? ts中 ?.、??、!.、_、** 等符號的含義?

        • ?. 可選鏈
        • ?? ?? 類似與短路或,??避免了一些意外情況0,NaN以及"",false被視為false值。只有undefind,null被視為false值。
        • !. 在變量名后添加!,可以斷言排除undefined和null類型
        • _ , 聲明該函數(shù)將被傳遞一個參數(shù),但您并不關(guān)心它
        • ** 求冪
        • !:,待會分配這個變量,ts不要擔(dān)心
        // ??
        let x = foo ?? bar();
        // 等價于
        let x = foo !== null && foo !== undefined ? foo : bar();

        // !.
        let a: string | null | undefined
        a.length // error
        a!.length // ok
        復(fù)制代碼

        ?? 什么是抗變、雙變、協(xié)變和逆變?

        • Covariant 協(xié)變,TS對象兼容性是協(xié)變,父類 <= 子類,是可以的。子類 <= 父類,錯誤。
        • Contravariant 逆變,禁用strictFunctionTypes編譯,函數(shù)參數(shù)類型是逆變的,父類 <= 子類,是錯誤。子類 <= 父類,是可以的。
        • Bivariant 雙向協(xié)變,函數(shù)參數(shù)的類型默認(rèn)是雙向協(xié)變的。父類 <= 子類,是可以的。子類 <= 父類,是可以的。

        ?? ts中同名的interface或者同名的interface和class可以合并嗎?

        1. interface會合并
        2. class不可以合并

        ?? 如何使ts項目引入并識別編譯為js的npm庫包?

        1. npm install @types/xxxx
        2. 自己添加描述文件

        ?? ts如何自動生成庫包的聲明文件?

        可以配置tsconfig.json文件中的declarationoutDir

        1. declaration: true, 將會自動生成聲明文件
        2. outDir: '', 指定目錄

        ?? 什么是泛型

        泛型用來來創(chuàng)建可重用的組件,一個組件可以支持多種類型的數(shù)據(jù)。這樣用戶就可以以自己的數(shù)據(jù)類型來使用組件。簡單的說,“泛型就是把類型當(dāng)成參數(shù)”。

        ?? -?,-readonly 是什么含義

        用于刪除修飾符

        type A = {
            a: string;
            b: number;
        }

        type B = {
            [K in keyof A]?: A[K]
        }

        type C = {
            [K in keyof B]-?: B[K]
        }

        type D = {
            readonly [K in keyof A]: A[K]
        }

        type E = {
            -readonly [K in keyof A]: A[K]
        }
        復(fù)制代碼

        ?? TS是基于結(jié)構(gòu)類型兼容

        typescript的類型兼容是基于結(jié)構(gòu)的,不是基于名義的。下面的代碼在ts中是完全可以的,但在java等基于名義的語言則會拋錯。

        interface Named { name: string }
        class Person {
          name: string
        }
        let p: Named
        // ok
        p = new Person()
        復(fù)制代碼

        ?? const斷言

        const斷言,typescript會為變量添加一個自身的字面量類型

        1. 對象字面量的屬性,獲得readonly的屬性,成為只讀屬性
        2. 數(shù)組字面量成為readonly tuple只讀元組
        3. 字面量類型不能被擴(kuò)展(比如從hello類型到string類型)
        // type '"hello"'
        let x = "hello" as const
        // type 'readonly [10, 20]'
        let y = [1020as const
        // type '{ readonly text: "hello" }'
        let z = { text: "hello" } as const
        復(fù)制代碼

        ?? type 和 interface 的區(qū)別

        1. 類型別名可以為任何類型引入名稱。例如基本類型,聯(lián)合類型等
        2. 類型別名不支持繼承
        3. 類型別名不會創(chuàng)建一個真正的名字
        4. 類型別名無法被實現(xiàn)(implements),而接口可以被派生類實現(xiàn)
        5. 類型別名重名時編譯器會拋出錯誤,接口重名時會產(chǎn)生合并

        ?? implements 與 extends 的區(qū)別

        • extends, 子類會繼承父類的所有屬性和方法。
        • implements,使用implements關(guān)鍵字的類將需要實現(xiàn)需要實現(xiàn)的類的所有屬性和方法。

        ?? 枚舉和 object 的區(qū)別

        1. 枚舉可以通過枚舉的名稱,獲取枚舉的值。也可以通過枚舉的值獲取枚舉的名稱。
        2. object只能通過key獲取value
        3. 數(shù)字枚舉在不指定初始值的情況下,枚舉值會從0開始遞增。
        4. 雖然在運行時,枚舉是一個真實存在的對象。但是使用keyof時的行為卻和普通對象不一致。必須使用keyof typeof才可以獲取枚舉所有屬性名。

        ?? never, void 的區(qū)別

        • never,never表示永遠(yuǎn)不存在的類型。比如一個函數(shù)總是拋出錯誤,而沒有返回值。或者一個函數(shù)內(nèi)部有死循環(huán),永遠(yuǎn)不會有返回值。函數(shù)的返回值就是never類型。
        • void, 沒有顯示的返回值的函數(shù)返回值為void類型。如果一個變量為void類型,只能賦予undefined或者null。

        unknown, any的區(qū)別

        unknown類型和any類型類似。與any類型不同的是。unknown類型可以接受任意類型賦值,但是unknown類型賦值給其他類型前,必須被斷言

        ?? 如何在 window 擴(kuò)展類型

        declare global {
          interface Window {
            myCustomFn: () => void;
          }
        }
        復(fù)制代碼

        復(fù)雜的類型推導(dǎo)題目

        ?? implement UnionToIntersection

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

        // 實現(xiàn)UnionToIntersection<T>
        type UnionToIntersection<U> = 
          (extends any ? (k: U) => void : neverextends ((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
        復(fù)制代碼

        ?? implement ToNumber

        type A = ToNumber<'1'// 1
        type B = ToNumber<'40'// 40
        type C = ToNumber<'0'// 0

        // 實現(xiàn)ToNumber
        type ToNumber<T extends string, R extends any[] = []> =
            T extends `${R['length']}` ? R['length'] : ToNumber<T, [1, ...R]>;
        復(fù)制代碼

        ?? implement Add<A, B>

        type A = Add<12// 3
        type B = Add<00// 0

        // 實現(xiàn)ADD
        type NumberToArray<T, R extends any[]> = T extends R['length'] ? R : NumberToArray<T, [1, ...R]>
        type Add<T, R> = [...NumberToArray<T, []>, ...NumberToArray<R, []>]['length']
        復(fù)制代碼

        ?? implement SmallerThan<A, B>

        type A = SmallerThan<01// true
        type B = SmallerThan<10// false
        type C = SmallerThan<109// false

        // 實現(xiàn)SmallerThan
        type SmallerThan<N extends number, M extends number, L extends any[] = [], R extends any[] = []> = 
            N extends L['length'] ? 
                M extends R['length'] ? false : true
                :
                M extends R['length'] ? false : SmallerThan<N, M, [1, ...L], [1, ...R]>;
        復(fù)制代碼

        ?? implement LargerThan<A, B>

        type A = LargerThan<01// false
        type B = LargerThan<10// true
        type C = LargerThan<109// true

        // 實現(xiàn)LargerThan
        type LargerThan<N extends number, M extends number, L extends any[] = [], R extends any[] = []> =
            N extends L['length'] ?
                false : M extends R['length'] ?
                    true : LargerThan<N, M, [1, ...L], [1, ...R]>;
        復(fù)制代碼

        ?? implement IsAny

        type A = IsAny<string// false
        type B = IsAny<any// true
        type C = IsAny<unknown> // false
        type D = IsAny<never> // false

        // 實現(xiàn)IsAny
        type IsAny<T> = true extends (T extends never ? true : false) ?
                          false extends (T extends never ? true : false) ?
                            true
                            :
                            false
                          :
                          false;

        // 更簡單的實現(xiàn)
        type IsAny<T> = 0 extends (T & 1) ? true : false;
        復(fù)制代碼

        ?? implement Filter<T, A>

        type A = Filter<[1,'BFE'2true'dev'], number// [1, 2]
        type B = Filter<[1,'BFE'2true'dev'], string// ['BFE', 'dev']
        type C = Filter<[1,'BFE'2any'dev'], string// ['BFE', any, 'dev']

        // 實現(xiàn)Filter
        type Filter<T extends any[], A, N extends any[] = []> =
            T extends [infer P, ...infer Q] ?
                0 extends (P & 1) ? Filter<Q, A, [...N, P]> : 
                P extends A ? Filter<Q, A, [...N, P]> : Filter<Q, A, N>
                : N;
        復(fù)制代碼

        ?? implement TupleToString

        type A = TupleToString<['a']> // 'a'
        type B = TupleToString<['B''F''E']> // 'BFE'
        type C = TupleToString<[]> // ''

        // 實現(xiàn)TupleToString
        type TupleToString<T extends any[], S extends string = '', A extends any[] = []> =
            A['length'extends T['length'] ? S : TupleToString<T, `${S}${T[A['length']]}`, [1, ...A]>
        復(fù)制代碼

        ?? implement RepeatString<T, C>

        type A = RepeatString<'a'3// 'aaa'
        type B = RepeatString<'a'0// ''

        // 實現(xiàn)RepeatString
        type RepeatString<T extends string, C extends number, S extends string = '', A extends any[] = []> =
            A['length'extends C ? S : RepeatString<T, C, `${T}${S}`, [1, ...A]>
        復(fù)制代碼

        ?? implement Push<T, I>

        type A = Push<[1,2,3], 4// [1,2,3,4]
        type B = Push<[1], 2// [1, 2]
        type C = Push<[], string// [string]

        // 實現(xiàn)Push
        type Push<T extends any[], I> = T extends [...infer P] ? [...P, I] : [I]
        復(fù)制代碼

        ?? implement Flat

        type A = Flat<[1,2,3]> // [1,2,3]
        type B = Flat<[1,[2,3], [4,[5,[6]]]]> // [1,2,3,4,5,6]
        type C = Flat<[]> // []

        // 實現(xiàn)Flat
        type Flat<T extends any[]> =
            T extends [infer P, ...infer Q] ?
                P extends any[] ? [...Flat<P>, ...Flat<Q>] : [P, ...Flat<Q>]
                : [];
        復(fù)制代碼

        ?? implement Shift

        type A = Shift<[1,2,3]> // [2,3]
        type B = Shift<[1]> // []
        type C = Shift<[]> // []

        // 實現(xiàn)Shift
        type Shift<T extends any[]> = T extends [infer P, ...infer Q] ? [...Q] : [];
        復(fù)制代碼

        ?? implement Repeat<T, C>

        type A = Repeat<number3// [number, number, number]
        type B = Repeat<string2// [string, string]
        type C = Repeat<11// [1, 1]
        type D = Repeat<00// []

        // 實現(xiàn)Repeat
        type Repeat<T, C, R extends any[] = []> = 
            R['length'extends C ? R : Repeat<T, C, [...R, T]>
        復(fù)制代碼

        ?? implement ReverseTuple

        type A = ReverseTuple<[stringnumberboolean]> // [boolean, number, string]
        type B = ReverseTuple<[1,2,3]> // [3,2,1]
        type C = ReverseTuple<[]> // []

        // 實現(xiàn)ReverseTuple
        type ReverseTuple<T extends any[], A extends any[] = []> =
            T extends [...infer Q, infer P] ? 
                A['length'extends T['length'] ? A : ReverseTuple<Q, [...A, P]>
                : A;
        復(fù)制代碼

        ?? implement UnwrapPromise

        type A = UnwrapPromise<Promise<string>> // string
        type B = UnwrapPromise<Promise<null>> // null
        type C = UnwrapPromise<null// Error

        // 實現(xiàn)UnwrapPromise
        type UnwrapPromise<T> = T extends Promise<infer P> ? P : Error;
        復(fù)制代碼

        ?? implement LengthOfString

        type A = LengthOfString<'BFE.dev'// 7
        type B = LengthOfString<''// 0

        // 實現(xiàn)LengthOfString
        type LengthOfString<T extends string, A extends any[] = []> =
            T extends `${infer P}${infer Q}` ? LengthOfString<Q, [1, ...A]> : A['length']
        復(fù)制代碼

        ?? implement StringToTuple

        type A = StringToTuple<'BFE.dev'// ['B', 'F', 'E', '.', 'd', 'e','v']
        type B = StringToTuple<''// []

        // 實現(xiàn)
        type StringToTuple<T extends string, A extends any[] = []> =
            T extends `${infer K}${infer P}` ? StringToTuple<P, [...A, K]> : A;
        復(fù)制代碼

        ?? implement LengthOfTuple

        type A = LengthOfTuple<['B''F''E']> // 3
        type B = LengthOfTuple<[]> // 0

        // 實現(xiàn)
        type LengthOfTuple<T extends any[], R extends any[] = []> =
            R['length'extends T['length'] ? R['length'] : LengthOfTuple<T, [...R, 1]>
        復(fù)制代碼

        ?? implement LastItem

        type A = LastItem<[stringnumberboolean]> // boolean
        type B = LastItem<['B''F''E']> // 'E'
        type C = LastItem<[]> // never

        // 實現(xiàn)LastItem
        type LastItem<T> = T extends [...infer P, infer Q] ? Q : never;
        復(fù)制代碼

        ?? implement FirstItem

        type A = FirstItem<[stringnumberboolean]> // string
        type B = FirstItem<['B''F''E']> // 'B'

        // 實現(xiàn)FirstItem
        type FirstItem<T> = T extends [infer P, ...infer Q] ? P : never;
        復(fù)制代碼

        ?? implement FirstChar

        type A = FirstChar<'BFE'// 'B'
        type B = FirstChar<'dev'// 'd'
        type C = FirstChar<''// never

        // 實現(xiàn)FirstChar
        type FirstChar<T> = T extends `${infer P}${infer Q}` ? P : never;
        復(fù)制代碼

        ?? implement Pick<T, K>

        type Foo = {
          a: string
          b: number
          c: boolean
        }

        type A = MyPick<Foo, 'a' | 'b'// {a: string, b: number}
        type B = MyPick<Foo, 'c'// {c: boolean}
        type C = MyPick<Foo, 'd'// Error

        // 實現(xiàn)MyPick<T, K>
        type MyPick<T, K extends keyof T> = {
            [Key in K]: T[Key]
        }
        復(fù)制代碼

        ?? implement Readonly

        type Foo = {
          a: string
        }

        const a:Foo = {
          a: 'BFE.dev',
        }
        a.a = 'bigfrontend.dev'
        // OK

        const b:MyReadonly<Foo> = {
          a: 'BFE.dev'
        }
        b.a = 'bigfrontend.dev'
        // Error

        // 實現(xiàn)MyReadonly
        type MyReadonly<T> = {
            readonly [K in keyof T]: T[K]
        }
        復(fù)制代碼

        ?? implement Record<K, V>

        type Key = 'a' | 'b' | 'c'

        const a: Record<Key, string> = {
          a: 'BFE.dev',
          b: 'BFE.dev',
          c: 'BFE.dev'
        }
        a.a = 'bigfrontend.dev' // OK
        a.b = 123 // Error
        a.d = 'BFE.dev' // Error

        type Foo = MyRecord<{a: string}, string// Error

        // 實現(xiàn)MyRecord
        type MyRecord<K extends number | string | symbol, V> = {
            [Key in K]: V
        }
        復(fù)制代碼

        ??? implement Exclude

        type Foo = 'a' | 'b' | 'c'

        type A = MyExclude<Foo, 'a'// 'b' | 'c'
        type B = MyExclude<Foo, 'c'// 'a' | 'b
        type C = MyExclude<Foo, 'c' | 'd'>  // 'a' | 'b'
        type D = MyExclude<Foo, 'a' | 'b' | 'c'>  // never

        // 實現(xiàn) MyExclude<T, K>
        type MyExclude<T, K> = T extends K ? never : T;
        復(fù)制代碼

        ??? implement Extract<T, U>

        type Foo = 'a' | 'b' | 'c'

        type A = MyExtract<Foo, 'a'// 'a'
        type B = MyExtract<Foo, 'a' | 'b'// 'a' | 'b'
        type C = MyExtract<Foo, 'b' | 'c' | 'd' | 'e'>  // 'b' | 'c'
        type D = MyExtract<Foo, never>  // never

        // 實現(xiàn)MyExtract<T, U>
        type MyExtract<T, U> = T extends U ? T : never
        復(fù)制代碼

        ?? implement Omit<T, K>

        type Foo = {
          a: string
          b: number
          c: boolean
        }

        type A = MyOmit<Foo, 'a' | 'b'// {c: boolean}
        type B = MyOmit<Foo, 'c'// {a: string, b: number}
        type C = MyOmit<Foo, 'c' | 'd'// {a: string, b: number}

        // 實現(xiàn)MyOmit
        type MyOmit<T, K extends number | string | symbol> = {
            [Key in Exclude<keyof T, K>]: T[Key]
        }

        type MyOmit<T, K extends number | string | symbol> = Pick<T, Exclude<keyof T, K>>
        復(fù)制代碼

        ?? implement NonNullable

        type Foo = 'a' | 'b' | null | undefined

        type A = MyNonNullable<Foo> // 'a' | 'b'

        // 實現(xiàn)NonNullable
        type MyNonNullable<T> = T extends null | undefined ? never : T;
        復(fù)制代碼

        ?? implement Parameters

        type Foo = (a: string, b: number, c: boolean) => string

        type A = MyParameters<Foo> // [a:string, b: number, c:boolean]
        type B = A[0// string
        type C = MyParameters<{a: string}> // Error

        // 實現(xiàn)MyParameters<T>
        type MyParameters<T extends (...params: any[]) => any> =
            T extends (...params: [...infer P]) => any ? P : never
        復(fù)制代碼

        ?? implement ConstructorParameters

        class Foo {
          constructor (a: string, b: number, c: boolean) {}
        }

        type C = MyConstructorParameters<typeof Foo> 
        // [a: string, b: number, c: boolean]

        // 實現(xiàn)MyConstructorParameters<T>
        type MyConstructorParameters<T extends new (...params: any[]) => any> =
            T extends new (...params: [...infer P]) => any ? P : never
        復(fù)制代碼

        ?? implement ReturnType

        type Foo = () => {a: string}

        type A = MyReturnType<Foo> // {a: string}

        // 實現(xiàn)MyReturnType<T>
        type MyReturnType<T extends (...params: any[]) => any> =
            T extends (...params: any[]) => infer P ? P : never;
        復(fù)制代碼

        ?? implement InstanceType

        class Foo {}
        type A = MyInstanceType<typeof Foo> // Foo
        type B = MyInstanceType<() => string// Error

        // 實現(xiàn)MyInstanceType<T>
        type MyInstanceType<T extends new (...params: any[]) => any> =
            T extends new (...params: any[]) => infer P ? P : never;
        復(fù)制代碼

        ?? implement ThisParameterType

        function Foo(this: {a: string}{}
        function Bar() {}

        type A = MyThisParameterType<typeof Foo> // {a: string}
        type B = MyThisParameterType<typeof Bar> // unknown

        // 實現(xiàn)MyThisParameterType<T>
        type MyThisParameterType<T extends (thisany, ...params: any[]) => any> =
            T extends (this: infer P, ...params: any[]) => any ? P : unknown;
        復(fù)制代碼

        ?? implement TupleToUnion

        type Foo = [stringnumberboolean]

        type Bar = TupleToUnion<Foo> // string | number | boolean

        // 實現(xiàn)TupleToUnion<T>
        type TupleToUnion<T extends any[], R = T[0]> =
            T extends [infer P, ...infer Q] ? TupleToUnion<Q, R | P> : R;

        // 其他回答
        type TupleToUnion<T extends any[]> = T[number]
        復(fù)制代碼

        ?? implement Partial

        type Foo = {
          a: string
          b: number
          c: boolean
        }

        // below are all valid

        const a: MyPartial<Foo> = {}

        const b: MyPartial<Foo> = {
          a: 'BFE.dev'
        }

        const c: MyPartial<Foo> = {
          b: 123
        }

        const d: MyPartial<Foo> = {
          b: 123,
          c: true
        }

        const e: MyPartial<Foo> = {
          a: 'BFE.dev',
          b: 123,
          c: true
        }

        // 實現(xiàn)MyPartial<T>
        type MyPartial<T> = {
            [K in keyof T]?: T[K]
        }
        復(fù)制代碼

        ?? Required

        // all properties are optional
        type Foo = {
          a?: string
          b?: number
          c?: boolean
        }


        const a: MyRequired<Foo> = {}
        // Error

        const b: MyRequired<Foo> = {
          a: 'BFE.dev'
        }
        // Error

        const c: MyRequired<Foo> = {
          b: 123
        }
        // Error

        const d: MyRequired<Foo> = {
          b: 123,
          c: true
        }
        // Error

        const e: MyRequired<Foo> = {
          a: 'BFE.dev',
          b: 123,
          c: true
        }
        // valid

        // 實現(xiàn)MyRequired<T>
        type MyRequired<T> = {
            [K in keyof T]-?: T[K]
        }
        復(fù)制代碼

        ?? implement LastChar

        type A = LastChar<'BFE'// 'E'
        type B = LastChar<'dev'// 'v'
        type C = LastChar<''// never

        // 實現(xiàn)FirstChar<T>
        type LastChar<T extends string, A extends string[] = []> =
            T extends `${infer P}${infer Q}` ?  LastChar<Q, [...A, P]> :
                A extends [...infer L, infer R] ? R : never
        ;
        復(fù)制代碼

        ?? implement IsNever

        // https://stackoverflow.com/questions/53984650/typescript-never-type-inconsistently-matched-in-conditional-type
        // https://www.typescriptlang.org/docs/handbook/advanced-types.html#v
        type A = IsNever<never> // true
        type B = IsNever<string// false
        type C = IsNever<undefined// false

        // 實現(xiàn)IsNever<T>
        type IsNever<T> = [T] extends [never] ? true : false;
        復(fù)制代碼

        ?? implement KeysToUnion

        type A = KeyToUnion<{
          a: string;
          b: number;
          c: symbol;
        }>
        // 'a' | 'b' | 'c'

        // 實現(xiàn)KeyToUnion
        type KeyToUnion<T> = {
          [K in keyof T]: K;
        }[keyof T]
        復(fù)制代碼

        ?? implement ValuesToUnion

        type A = ValuesToUnion<{
          a: string;
          b: number;
          c: symbol;
        }>
        // string | number | symbol

        // ValuesToUnion
        type ValuesToUnion<T> = T[keyof T]
        復(fù)制代碼

        FindIndex<T, E>

        bigfrontend.dev/zh/typescri…[2]

        type IsAny<T> = 0 extends (T & 1) ? true : false;
        type IsNever<T> = [T] extends [never] ? true : false;

        type TwoAny<A, B> = IsAny<A> extends IsAny<B> ? IsAny<A> : false;
        type TwoNever<A, B> = IsNever<A> extends IsNever<B> ? IsNever<A> : false;

        type SingleAny<A, B> = IsAny<A> extends true ? true : IsAny<B>
        type SingleNever<A, B> = IsNever<A> extends true ? true : IsNever<B>


        type FindIndex<T extends any[], E, A extends any[] = []> =
            T extends [infer P, ...infer Q] ?
                TwoAny<P, E> extends true ? 
                    A['length']
                    :
                    TwoNever<P, E> extends true ?
                        A['length']
                        :
                        SingleAny<P, E> extends true ?
                            FindIndex<Q, E, [1, ...A]>
                            :
                            SingleNever<P, E> extends true ?
                                FindIndex<Q, E, [1, ...A]>
                                :
                                P extends E ? A['length'] : FindIndex<Q, E, [1, ...A]>
                : 
                never
        復(fù)制代碼

        implement Trim

        type A = Trim<'    BFE.dev'// 'BFE'
        type B = Trim<' BFE. dev  '// 'BFE. dev'
        type C = Trim<'  BFE .   dev  '// 'BFE .   dev'

        type StringToTuple<T extends string, A extends any[] = []> =
            T extends `${infer K}${infer P}` ? StringToTuple<P, [...A, K]> : A;

        type TupleToString<T extends any[], S extends string = '', A extends any[] = []> =
            A['length'extends T['length'] ? S : TupleToString<T, `${S}${T[A['length']]}`, [1, ...A]>

        type Trim<T extends string, A extends any[] = StringToTuple<T>> =
            A extends [infer P, ...infer Q] ?
                P extends ' ' ?
                    Trim<T, Q>
                    :
                    A extends [...infer M, infer N] ? 
                        N extends ' ' ?
                            Trim<T, M>
                            :
                            TupleToString<A>
                        :
                        ''
                :
                '';
        復(fù)制代碼

        還有更多 UnionToTuple, IntersectionToUnion ?


        關(guān)于本文

        來源:dyhtps

        https://juejin.cn/post/6988763249982308382


        最后

        歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
        回復(fù)「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會很認(rèn)真的解答喲!
        回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
        回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
        如果這篇文章對你有幫助,在看」是最大的支持
         》》面試官也在看的算法資料《《
        “在看和轉(zhuǎn)發(fā)”就是最大的支持


        瀏覽 84
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
          
          

            1. 国产成人无码AA精品 | 操大骚逼网站 | 小舞3d同人18av黄漫网站 | 亚洲成人在线影视 | 国产 在线观看免费视频 |