<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【TS】1092- TypeScript 相關(guān)問題(含解答)

          共 34645字,需瀏覽 70分鐘

           ·

          2021-09-28 00:23


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

          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. 枚舉會被編譯時會編譯成一個對象,可以被當作對象使用
          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不要擔心
          // ??
          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ù)的類型默認是雙向協(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ù)類型來使用組件。簡單的說,“泛型就是把類型當成參數(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. 字面量類型不能被擴展(比如從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表示永遠不存在的類型。比如一個函數(shù)總是拋出錯誤,而沒有返回值。或者一個函數(shù)內(nèi)部有死循環(huán),永遠不會有返回值。函數(shù)的返回值就是never類型。
          • void, 沒有顯示的返回值的函數(shù)返回值為void類型。如果一個變量為void類型,只能賦予undefined或者null。

          unknown, any的區(qū)別

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

          ?? 如何在 window 擴展類型

          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

          聲明:文章著作權(quán)歸作者所有,如有侵權(quán),請聯(lián)系小編刪除。


          1. JavaScript 重溫系列(22篇全)
          2. ECMAScript 重溫系列(10篇全)
          3. JavaScript設(shè)計模式 重溫系列(9篇全)
          4. 正則 / 框架 / 算法等 重溫系列(16篇全)
          5. Webpack4 入門(上)|| Webpack4 入門(下)
          6. MobX 入門(上) ||  MobX 入門(下)
          7. 120+篇原創(chuàng)系列匯總

          回復(fù)“加群”與大佬們一起交流學(xué)習(xí)~

          點擊“閱讀原文”查看 120+ 篇原創(chuàng)文章

          瀏覽 59
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  翔田千里无码破解HD | 青青操网站 | 亚洲无码一区二区三区电影 | 天天日天天操天天插天天射 | 日韩av高清无码 五月天婷婷丁香网 |