TypeScript 相關(guān)問題(含解答)
點擊上方 前端瓶子君,關(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ū)別
-
const用于變量,readonly用于屬性 -
const在運行時檢查,readonly在編譯時檢查 -
使用const變量保存的數(shù)組,可以使用push,pop等方法。但是如果使用 ReadonlyArray<number>聲明的數(shù)組不能使用push,pop等方法。
?? 枚舉和常量枚舉(const枚舉)的區(qū)別
-
枚舉會被編譯時會編譯成一個對象,可以被當(dāng)作對象使用 -
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可以合并嗎?
-
interface會合并 -
class不可以合并
?? 如何使ts項目引入并識別編譯為js的npm庫包?
-
npm install @types/xxxx -
自己添加描述文件
?? ts如何自動生成庫包的聲明文件?
可以配置tsconfig.json文件中的declaration和outDir
-
declaration: true, 將會自動生成聲明文件 -
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會為變量添加一個自身的字面量類型
-
對象字面量的屬性,獲得readonly的屬性,成為只讀屬性 -
數(shù)組字面量成為readonly tuple只讀元組 -
字面量類型不能被擴展(比如從hello類型到string類型)
// type '"hello"'
let x = "hello" as const
// type 'readonly [10, 20]'
let y = [10, 20] as const
// type '{ readonly text: "hello" }'
let z = { text: "hello" } as const
復(fù)制代碼
?? type 和 interface 的區(qū)別
-
類型別名可以為任何類型引入名稱。例如基本類型,聯(lián)合類型等 -
類型別名不支持繼承 -
類型別名不會創(chuàng)建一個真正的名字 -
類型別名無法被實現(xiàn)(implements),而接口可以被派生類實現(xiàn) -
類型別名重名時編譯器會拋出錯誤,接口重名時會產(chǎn)生合并
?? implements 與 extends 的區(qū)別
-
extends, 子類會繼承父類的所有屬性和方法。 -
implements,使用implements關(guān)鍵字的類將需要實現(xiàn)需要實現(xiàn)的類的所有屬性和方法。
?? 枚舉和 object 的區(qū)別
-
枚舉可以通過枚舉的名稱,獲取枚舉的值。也可以通過枚舉的值獲取枚舉的名稱。 -
object只能通過key獲取value -
數(shù)字枚舉在不指定初始值的情況下,枚舉值會從0開始遞增。 -
雖然在運行時,枚舉是一個真實存在的對象。但是使用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 擴展類型
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> =
(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
復(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<1, 2> // 3
type B = Add<0, 0> // 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<0, 1> // true
type B = SmallerThan<1, 0> // false
type C = SmallerThan<10, 9> // 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<0, 1> // false
type B = LargerThan<1, 0> // true
type C = LargerThan<10, 9> // 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', 2, true, 'dev'], number> // [1, 2]
type B = Filter<[1,'BFE', 2, true, 'dev'], string> // ['BFE', 'dev']
type C = Filter<[1,'BFE', 2, any, '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<number, 3> // [number, number, number]
type B = Repeat<string, 2> // [string, string]
type C = Repeat<1, 1> // [1, 1]
type D = Repeat<0, 0> // []
// 實現(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<[string, number, boolean]> // [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<[string, number, boolean]> // 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<[string, number, boolean]> // 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 (this: any, ...params: any[]) => any> =
T extends (this: infer P, ...params: any[]) => any ? P : unknown;
復(fù)制代碼
?? implement TupleToUnion
type Foo = [string, number, boolean]
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
最后
評論
圖片
表情
