面试题typeScript

 

ts基础知识复习

https://juejin.cn/post/6844903981227966471#heading-79

 

ts中的访问修饰符

public,任何地方

private,只能在类的内部访问

protected,能在类的内部访问和子类中访问

readonly,属性设置为只读

const和readonly的区别

const用于变量,readonly用于属性

const在运行时检查,readonly在编译时检查

使用const变量保存的数组,可以使用push,pop等方法。但是如果使用ReadonlyArray声明的数组不能使用push,pop等方法。

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

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

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 extends infer P ? keyof P : never

 

type T = UnionKey

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可以合并吗?

interface会合并

class不可以合并

如何使ts项目引入并识别编译为js的npm库包?

npm install @types/xxxx

自己添加描述文件

ts如何自动生成库包的声明文件?

可以配置tsconfig.json文件中的declaration和outDir

 

declaration: true, 将会自动生成声明文件

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会为变量添加一个自身的字面量类型

 

对象字面量的属性,获得readonly的属性,成为只读属性

数组字面量成为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

type 和 interface 的区别

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

类型别名不支持继承

类型别名不会创建一个真正的名字

类型别名无法被实现(implements),而接口可以被派生类实现

类型别名重名时编译器会抛出错误,接口重名时会产生合并

implements 与 extends 的区别

extends, 子类会继承父类的所有属性和方法。

implements,使用implements关键字的类将需要实现需要实现的类的所有属性和方法。

枚举和 object 的区别

枚举可以通过枚举的名称,获取枚举的值。也可以通过枚举的值获取枚举的名称。

object只能通过key获取value

数字枚举在不指定初始值的情况下,枚举值会从0开始递增。

虽然在运行时,枚举是一个真实存在的对象。但是使用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

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

implement ToNumber

type A = ToNumber<'1'> // 1

type B = ToNumber<'40'> // 40

type C = ToNumber<'0'> // 0

 

// 实现ToNumber

type ToNumber =

    T extends `${R['length']}` ? R['length'] : ToNumber;

implement Add

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

type B = Add<0, 0> // 0

 

// 实现ADD

type NumberToArray = T extends R['length'] ? R : NumberToArray

type Add = [.

你可能感兴趣的:(前端,面试,typescript)