关于javascript:TypeScript面试题总结

7次阅读

共计 14604 个字符,预计需要花费 37 分钟才能阅读完成。

笔者最近被裁员后也在找工作,如果大家感觉文章不错,心愿能够提供内推机会

ts 基础知识温习

https://juejin.cn/post/684490…

😊 ts 中的拜访修饰符

  • public,任何中央
  • private,只能在类的外部拜访
  • protected,能在类的外部拜访和子类中拜访
  • readonly,属性设置为只读

😊 const 和 readonly 的区别

  1. const 用于变量,readonly 用于属性
  2. const 在运行时查看,readonly 在编译时查看
  3. 应用 const 变量保留的数组,能够应用 push,pop 等办法。然而如果应用 ReadonlyArray<number> 申明的数组不能应用 push,pop 等办法。

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

  4. 枚举会被编译时会编译成一个对象,能够被当作对象应用
  5. 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
// const 枚举
const enum Witcher {
  Ciri = 'Queen',
  Geralt = 'Geralt of Rivia'
}
const witchers: Witcher[] = [Witcher.Ciri, Witcher.Geralt]
// 编译后
// const witchers = ['Queen', 'Geralt of Rivia'

😊 ts 中 interface 能够给 Function/Array/Class 做申明吗?

// 函数类型
interface SearchFunc {(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {let result = source.search(subString);
  return result > -1;
}
// Array
interface StringArray {[index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];
// Class, constructor 存在于类的动态局部,所以不会查看
interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

class Clock implements ClockInterface {
    currentTime: Date;
    setTime(d: Date) {this.currentTime = d;}
    constructor(h: number, m: number) {}}

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

不理解

😊 ts 中如何枚举联结类型的 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>

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

  • ?. 可选链
  • ?? ?? 相似与短路或,?? 防止了一些意外状况 0,NaN 以及 ””,false 被视为 false 值。只有 undefind,null 被视为 false 值。
  • !. 在变量名后增加!,能够断言排除 undefined 和 null 类型
  • _ , 申明该函数将被传递一个参数,但您并不关怀它
  • ** 求幂
  • !:,待会调配这个变量,ts 不要放心
// ??
let x = foo ?? bar();
// 等价于
let x = foo !== null && foo !== undefined ? foo : bar();

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

😊 什么是抗变、双变、协变和逆变?

  • Covariant 协变,TS 对象兼容性是协变,父类 <= 子类,是能够的。子类 <= 父类,谬误。
  • Contravariant 逆变,禁用 strictFunctionTypes 编译,函数参数类型是逆变的,父类 <= 子类,是谬误。子类 <= 父类,是能够的。
  • Bivariant 双向协变,函数参数的类型默认是双向协变的。父类 <= 子类,是能够的。子类 <= 父类,是能够的。

    😊 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: ”, 指定目录

😊 什么是泛型

泛型用来来创立可重用的组件,一个组件能够反对多种类型的数据。这样用户就能够以本人的数据类型来应用组件。简略的说,“泛型就是把类型当成参数”。

😊 -?,-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]
}

😊 TS 是基于构造类型兼容

typescript 的类型兼容是基于构造的,不是基于名义的。上面的代码在 ts 中是齐全能够的,但在 java 等基于名义的语言则会抛错。

interface Named {name: string}
class Person {name: string}
let p: Named
// ok
p = new Person()

😊 const 断言

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

  1. 对象字面量的属性,取得 readonly 的属性,成为只读属性
  2. 数组字面量成为 readonly tuple 只读元组
  3. 字面量类型不能被扩大(比方从 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

😊 type 和 interface 的区别

  1. 类型别名能够为任何类型引入名称。例如根本类型,联结类型等
  2. 类型别名不反对继承
  3. 类型别名不会创立一个真正的名字
  4. 类型别名无奈被实现(implements),而接口能够被派生类实现
  5. 类型别名重名时编译器会抛出谬误,接口重名时会产生合并

😊 implements 与 extends 的区别

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

    😊 枚举和 object 的区别

  1. 枚举能够通过枚举的名称,获取枚举的值。也能够通过枚举的值获取枚举的名称。
  2. object 只能通过 key 获取 value
  3. 数字枚举在不指定初始值的状况下,枚举值会从 0 开始递增。
  4. 尽管在运行时,枚举是一个实在存在的对象。然而应用 keyof 时的行为却和一般对象不统一。必须应用 keyof typeof 才能够获取枚举所有属性名。

😊 never, void 的区别

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

unknown, any 的区别

unknown 类型和 any 类型相似。与 any 类型不同的是。unknown 类型能够承受任意类型赋值,然而 unknown 类型赋值给其余类型前,必须被断言

😊 如何在 window 扩大类型

declare global {
  interface Window {myCustomFn: () => void;
  }
}

简单的类型推导题目

🤔 implement UnionToIntersection<T>

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

// 实现 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

😊 implement ToNumber<T>

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

// 实现 ToNumber
type ToNumber<T extends string, R extends any[] = []> =
    T extends `${R['length']}` ? R['length'] : ToNumber<T, [1, ...R]>;

😊 implement Add<A, B>

type A = Add<1, 2> // 3
type B = Add<0, 0> // 0

// 实现 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']

😊 implement SmallerThan<A, B>

type A = SmallerThan<0, 1> // true
type B = SmallerThan<1, 0> // false
type C = SmallerThan<10, 9> // false

// 实现 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]>;

😊 implement LargerThan<A, B>

type A = LargerThan<0, 1> // false
type B = LargerThan<1, 0> // true
type C = LargerThan<10, 9> // true

// 实现 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]>;

😊 implement IsAny<T>

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

// 实现 IsAny
type IsAny<T> = true extends (T extends never ? true : false) ?
                  false extends (T extends never ? true : false) ?
                    true
                    :
                    false
                  :
                  false;

// 更简略的实现
type IsAny<T> = 0 extends (T & 1) ? true : false;

😊 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']

// 实现 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;

😊 implement TupleToString<T>

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

// 实现 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]>

😊 implement RepeatString<T, C>

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

// 实现 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]>

😊 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]

// 实现 Push
type Push<T extends any[], I> = T extends [...infer P] ? [...P, I] : [I]

😊 implement Flat<T>

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<[]> // []

// 实现 Flat
type Flat<T extends any[]> =
    T extends [infer P, ...infer Q] ?
        P extends any[] ? [...Flat<P>, ...Flat<Q>] : [P, ...Flat<Q>]
        : [];

😊 implement Shift<T>

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

// 实现 Shift
type Shift<T extends any[]> = T extends [infer P, ...infer Q] ? [...Q] : [];

😊 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> // []

// 实现 Repeat
type Repeat<T, C, R extends any[] = []> = 
    R['length'] extends C ? R : Repeat<T, C, [...R, T]>

😊 implement ReverseTuple<T>

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

// 实现 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;

😊 implement UnwrapPromise<T>

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

// 实现 UnwrapPromise
type UnwrapPromise<T> = T extends Promise<infer P> ? P : Error;

😊 implement LengthOfString<T>

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

// 实现 LengthOfString
type LengthOfString<T extends string, A extends any[] = []> =
    T extends `${infer P}${infer Q}` ? LengthOfString<Q, [1, ...A]> : A['length']

😊 implement StringToTuple<T>

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

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

😊 implement LengthOfTuple<T>

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

// 实现
type LengthOfTuple<T extends any[], R extends any[] = []> =
    R['length'] extends T['length'] ? R['length'] : LengthOfTuple<T, [...R, 1]>

😊 implement LastItem<T>

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

// 实现 LastItem
type LastItem<T> = T extends [...infer P, infer Q] ? Q : never;

😊 implement FirstItem<T>

type A = FirstItem<[string, number, boolean]> // string
type B = FirstItem<['B', 'F', 'E']> // 'B'

// 实现 FirstItem
type FirstItem<T> = T extends [infer P, ...infer Q] ? P : never;

😊 implement FirstChar<T>

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

// 实现 FirstChar
type FirstChar<T> = T extends `${infer P}${infer Q}` ? P : never;

😊 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

// 实现 MyPick<T, K>
type MyPick<T, K extends keyof T> = {[Key in K]: T[Key]
}

😊 implement Readonly<T>

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

// 实现 MyReadonly
type MyReadonly<T> = {readonly [K in keyof T]: T[K]
}

😊 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

// 实现 MyRecord
type MyRecord<K extends number | string | symbol, V> = {[Key in K]: V
}

🤔️ 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

// 实现 MyExclude<T, K>
type MyExclude<T, K> = T extends K ? never : T;

🤔️ 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

// 实现 MyExtract<T, U>
type MyExtract<T, U> = T extends U ? T : never

😊 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}

// 实现 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>>

😊 implement NonNullable<T>

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

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

// 实现 NonNullable
type MyNonNullable<T> = T extends null | undefined ? never : T;

😊 implement Parameters<T>

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

// 实现 MyParameters<T>
type MyParameters<T extends (...params: any[]) => any> =
    T extends (...params: [...infer P]) => any ? P : never

😊 implement ConstructorParameters<T>

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

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

// 实现 MyConstructorParameters<T>
type MyConstructorParameters<T extends new (...params: any[]) => any> =
    T extends new (...params: [...infer P]) => any ? P : never

😊 implement ReturnType<T>

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

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

// 实现 MyReturnType<T>
type MyReturnType<T extends (...params: any[]) => any> =
    T extends (...params: any[]) => infer P ? P : never;

😊 implement InstanceType<T>

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

// 实现 MyInstanceType<T>
type MyInstanceType<T extends new (...params: any[]) => any> =
    T extends new (...params: any[]) => infer P ? P : never;

😊 implement ThisParameterType<T>

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

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

// 实现 MyThisParameterType<T>
type MyThisParameterType<T extends (this: any, ...params: any[]) => any> =
    T extends (this: infer P, ...params: any[]) => any ? P : unknown;

😊 implement TupleToUnion<T>

type Foo = [string, number, boolean]

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

// 实现 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]

😊 implement Partial<T>

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
}

// 实现 MyPartial<T>
type MyPartial<T> = {[K in keyof T]?: T[K]
}

😊 Required<T>

// 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

// 实现 MyRequired<T>
type MyRequired<T> = {[K in keyof T]-?: T[K]
}

😊 implement LastChar<T>

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

// 实现 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
;

😊 implement IsNever<T>

// 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

// 实现 IsNever<T>
type IsNever<T> = [T] extends [never] ? true : false;

😊 implement KeysToUnion<T>

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

// 实现 KeyToUnion
type KeyToUnion<T> = {[K in keyof T]: K;
}[keyof T]

😊 implement ValuesToUnion<T>

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

// ValuesToUnion
type ValuesToUnion<T> = T[keyof T]

FindIndex<T, E>

https://bigfrontend.dev/zh/ty…

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

implement Trim<T>

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>
                :
                '':'';

还有更多 UnionToTuple, IntersectionToUnion ?

正文完
 0