跟chatGPT一起复习前端 —— TypeScript

173 阅读10分钟

前言

又到一波面试准备的时刻,整理了一波前端相关要点内容,配合chatGPT完成要点内容整理,有纠正错误和需要补充的小伙伴可以在这里留言,及时更新。

为什么推荐使用TypeScript

TypeScript是JavaScript的超集,它扩展了JavaScript的语法,因此现有的JavaScript代码可与TypeScript一起工作无需任何修改。TypeScript通过类型注解提供编译时的静态类型检查,这使得代码更加可靠和容易重构。

以下是一些推荐使用TypeScript的原因:

  • bug 显著减少,类型相关 bug 直线减少。
  • 应用更可控,当你需要约束某些代码的时候,用类型就能很简单地做到。
  • 查文档更方便,以前要打开浏览器看文档,现在直接查看定义就基本明白了。

TypeScript的主要特点是什么

TypeScript是JavaScript的一个超集,主要提供了类型系统和对ES6+的支持,让JavaScript变成强类型语言。它由Microsoft开发,代码开源于GitHub上。TypeScript的主要特点包括:

  • 跨平台:TypeScript编译器可以安装在任何操作系统上,包括Windows、macOS和Linux。
  • ES6特性:TypeScript包含计划中的ECMAScript 2015 (ES6)的大部分特性,例如箭头函数。
  • 面向对象的语言:TypeScript提供所有标准的OOP功能,如类、接口和模块。
  • 静态类型检查:TypeScript使用静态类型并帮助在编译时捕获错误,从而提高代码质量和可维护性。
  • 工具支持:TypeScript具有广泛的工具支持,包括编辑器、IDE、构建工具和测试框架等。

TypeScript和JavaScript的区别是什么

TypeScript 是 JavaScript 的超集,包含了 JavaScript 的所有元素,可以载入 JavaScript 代码运行,并扩展了 JavaScript 的语法。TypeScript 是一种面向对象的编程语言,由 Microsoft 开发和维护。TypeScript 可以在编译时进行类型检查,这意味着在编写代码时可以更早地发现错误。此外,TypeScript 还提供了一些其他的功能,如接口、泛型、枚举等等。

TypeScript中有哪些声明变量的方式

在TypeScript中,可以使用以下四种方式来声明变量:var、let、const和import。

  • var:使用关键字var声明变量,其作用域为该语句所在的函数内,且存在变量提升现象。
  • let:使用关键字let声明变量,其作用域为该语句所在的代码块内,不存在变量提升。
  • const:使用关键字const声明常量,其作用域为该语句所在的代码块内,一旦被赋值就不能再次赋值。
  • import:使用关键字import导入模块。
  • 总之,在TypeScript中,有多种方式可以声明变量,开发人员可以根据需要选择最适合自己的方式。

TypeScript的内置数据类型

在TypeScript中,内置的数据类型包括以下几种:boolean、number、string、array、tuple、enum、any和void。

  • boolean:表示逻辑上的 true 或 false 值。
  • number:表示数字,可以是整数或浮点数。
  • string:表示字符串。
  • array:表示一组具有相同类型的值的集合。
  • tuple:表示已知元素数量和类型的数组。
  • enum:表示一组有名字的常量集合。
  • any:表示任何类型的值。
  • void:表示没有任何返回值的函数。

TypeScript中泛型是什么

在 TypeScript 中,泛型是一种创建可复用代码组件的工具。泛型允许我们在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。在 TypeScript 中,定义函数、接口或类的时候,不预先定义好具体的类型,而在使用的时候再指定类型的一种特性。泛型可以解决类、接口、方法的复用性,以及对不特定数据类型的支持.

TypeScript中泛型怎么使用

泛型是TypeScript中的一个重要特性,它可以让你在编写代码时更好地定义和使用类型。在TypeScript中,你可以使用泛型来创建可重用的组件和函数,以及在编译时捕获类型错误。下面是一个简单的示例,展示了如何在TypeScript中使用泛型:

function identity<T>(arg: T): T {
    return arg;
}

let output = identity<string>("hello world");

console.log(output);

这个示例定义了一个名为identity的函数,它接受一个类型为T的参数,并返回一个类型为T的值。在这个示例中,我们将identity函数应用于一个字符串,并将其结果存储在变量output中。

TypeScript中never和void的区别

在 TypeScript 中,void 表示没有任何类型(可以被赋值为 null 和 undefined)。void 返回值类型的函数能正常运行。never 表示一个不包含值的类型,即表示永远不存在的值。它是那些总是会抛出异常或根本不会有返回值的函数表达式或箭头函数表达式的返回值类型。例如,一个函数表达式或箭头函数表达式,它们的返回类型被推断为 never,当它们抛出异常或根本不会有返回值时。

TypeScript中的类型断言是什么

类型断言(Type Assertion)是 TypeScript 中的一种语法,主要用于当 TypeScript 推断出来类型并不满足当前需求时,TypeScript 允许开发者覆盖它的推断,可以用来手动指定一个值的类型。在 TypeScript 中,类型断言有两种语法:as 语法和 <> 语法。

TypeScript中any和unknown有什么区别

在 TypeScript 中,any 和 unknown 都是顶级类型,但是它们之间有很大的区别。any 类型的变量可以被赋予任何值,而 unknown 类型的变量只能被赋予任何值或者 unknown 类型的值。此外,你不能在类型为 unknown 的值上调用或者构造任何东西,也不能访问它们的属性。

TypeScript中如何声明类?

在TypeScript中,声明类的方式与JavaScript中的方式相同。使用关键字class后跟类名,然后在大括号中定义类的属性和方法。例如,下面是一个简单的类声明:

class Car {
    // 字段
    engine: string;

    // 构造函数
    constructor(engine: string) {
        this.engine = engine;
    }

    // 方法
    start() {
        console.log("Engine started: " + this.engine);
    }
}

在上面的代码中,我们定义了一个名为Car的类,它有一个名为engine的属性和一个名为start的方法。构造函数用于初始化属性。

如果需要继承另一个类,则可以使用关键字extends。例如,下面是一个简单的继承示例:

class SportsCar extends Car {
    // 新字段
    topSpeed: number;

    constructor(engine: string, topSpeed: number) {
        super(engine);
        this.topSpeed = topSpeed;
    }

    // 新方法
    display() {
        console.log("Top speed: " + this.topSpeed);
    }
}

在上面的代码中,我们定义了一个名为SportsCar的类,它继承自Car类,并添加了一个名为topSpeed的新字段和一个名为display的新方法。构造函数使用关键字super()调用父类构造函数。

TypeScript中命名空间与模块的理解和区别

在 TypeScript 中,命名空间和模块都是用来组织代码的工具。命名空间是位于全局命名空间下的一个普通的带有名字的 JavaScript 对象,使用起来十分容易。但就像其它的全局命名空间污染一样,它很难去识别组件之间的依赖关系,尤其是在大型的应用中。而模块则可以声明它的依赖,可以更好地管理代码之间的依赖关系。模块可以包含代码和声明,并且可以导出其中的部分内容供其他模块使用。

TypeScript支持哪些访问修饰符

在 TypeScript 中,有三种访问修饰符:public、protected 和 private。默认情况下,类成员都是 public 的。public 成员可以在任何地方被访问。protected 成员可以被其自身以及其子类访问。private 成员只能被其定义所在的类访问。

TypeScript中的枚举是什么

在 TypeScript 中,枚举是一个被命名的整型常数的集合,用于声明一组命名的常数。当一个变量有几种可能的取值时,可以将它定义为枚举类型。

TypeScript装饰器

在 TypeScript 中,装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、属性或者参数上。装饰器使用 @expression 这种形式,expression 求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。

TypeScript中什么是类类型接口

类类型接口是一种特殊的接口,它可以用来描述类的实例部分的类型。类类型接口可以描述类的实例部分和类的构造函数部分。例如,下面的代码定义了一个类类型接口ClockInterface,它描述了一个拥有currentTime属性和setTime方法的类的实例部分,以及一个构造函数,该构造函数带有一个参数。

interface ClockConstructor {
    new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
    currentTime: Date;
    setTime(d: Date): void;
}

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

TS中什么是方法重载

方法重载是指在同一个类中方法同名,参数不同(参数类型不同、参数个数不同或参数个数相同时参数的先后顺序不同),调用时根据实参的形式,选择与它匹配的方法执行操作的一种技术。在TypeScript中,我们可以重载类中的成员方法。例如,下面的代码定义了一个类Calculator,它有两个重载的方法add,一个接受两个数字并返回它们的和,另一个接受三个数字并返回它们的和。

class Calculator {
    add(a: number, b: number): number;
    add(a: number, b: number, c: number): number;
    add(a: any, b: any, c?: any): number {
        if (c) {
            return a + b + c;
        } else {
            return a + b;
        }
    }
}

如何使用TypeScript mixin

TypeScript中的Mixin是一种伪多重继承模式,它允许您创建一个类,该类是许多类的合并。在TypeScript中,最好的Mixin支持是通过类表达式模式完成的。Mixin模式通过代码流分析在TypeScript编译器内部得到了支持。您可以在几种情况下遇到原生支持的边缘。

下面是一个使用Mixin的示例代码:

type Constructor<T = {}> = new (...args: any[]) => T;

function Timestamped<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    timestamp = Date.now();
  };
}

function Tagged<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    tag = "hello";
  };
}

const TaggedTimestamped = Tagged(Timestamped(class {}));
class TaggedTimestamped2 extends Tagged(Timestamped(class {})) {}

console.log(new TaggedTimestamped());
console.log(new TaggedTimestamped2());

什么是TypeScript映射文件?

TypeScript映射文件是源映射文件,可让工具在发出的JavaScript代码和创建它的TypeScript源文件之间进行映射。

TypeScript中的interface和type有什么区别?

在TypeScript中,interface和type都可以用于定义对象类型,但是它们之间有一些区别。interface是一个合同,它定义了一个对象的形状,而type是一个别名,它定义了一个类型。123

interface可以扩展,而type不行。interface可以被类实现,而type不行。interface可以声明合并,而type不行。当您需要使用联合类型或元组类型时,请使用type。当您需要扩展或声明合并时,请使用interface。

TypeScript中的getter/setter是什么?你如何使用它们?

在TypeScript中,getter和setter是特殊类型的方法,可帮助您根据程序的需要委派对私有变量的不同级别的访问。getter使您能够引用一个值但不能编辑它,而setter使您能够更改变量的值,但不能查看其当前值。这些对于实现封装是必不可少的。

使用get和set关键字在TypeScript中定义getter和setter。getter使我们能够将属性绑定到在访问属性时调用的函数,而setter将属性绑定到在尝试设置属性时调用的函数。以下是一个示例:

class SomeClass {
    private _name: string = '';
    get name(): string {
        return this._name;
    }
    set name(value: string) {
        this._name = value;
    }
}

在上面的示例中,我们定义了一个名为SomeClass的类,并使用get和set关键字定义了一个名为name的属性。getter返回_name变量的值,而setter将_name变量设置为传递给它的值。这样,我们可以通过SomeClass实例访问name属性并读取或更改其值。

如何检查TypeScript中的null和undefiend?

在TypeScript中,您可以使用typeof运算符检查null和undefined。例如,以下代码段检查变量是否为null或undefined:

if (typeof someVariable === 'undefined' || someVariable === null) {
    // someVariable is either undefined or null
}

您还可以使用strictNullChecks编译器选项来启用严格的null检查。当启用此选项时,您必须显式处理可能为null或undefined的值。例如,以下代码段演示了如何使用可选链运算符(?.)和nullish合并运算符(??)来处理可能为null或undefined的值:

let someVariable: string | null | undefined;
let result = someVariable?.toUpperCase() ?? 'default';

在上面的示例中,我们定义了一个名为someVariable的变量,它可以是字符串、null或undefined。我们使用可选链运算符(?.)和nullish合并运算符(??)来处理someVariable的值。如果someVariable为null或undefined,则result将设置为’default’。否则,我们将调用toUpperCase()方法并将结果分配给result变量。

TypeScript中const和readonly的区别是什么?

在TypeScript中,const和readonly都用于定义常量,但它们有一些区别。const是静态常量,只能在声明时初始化,不能在运行时更改。另一方面,readonly是动态常量,可以在构造函数中初始化,并且可以在运行时更改。

另一个区别是,const默认是静态的,只能由类型来访问,不能与static同时使用。另一方面,readonly默认是非静态的,由实例对象来访问,并且可以使用static定义为静态成员。

TypeScript有哪些辅助类型

TypeScript提供了许多自带的工具类型,这些类型都是全局可用的,所以无须导入即可直接使用。以下是一些常用的辅助类型:

  • Partial<T>:将T中所有属性设置为可选属性。
  • Required<T> :将T中所有属性设置为必选属性。
  • Readonly<T> :将T中所有属性设置为只读属性。
  • Record<K,T> :创建一个由K类型的属性组成的对象,其属性值类型为T类型。
  • Pick<T,K> :从T中选择一组属性K并返回一个新对象。
  • Exclude<T,U> :从T中排除可以赋值给U的类型。
  • Omit<T,K> :从T中删除一组属性K并返回一个新对象。
  • Extract<T,U> :从T中提取可以赋值给U的类型。
  • NonNullable<T> :从T中排除null和undefined。

TypeScript的交叉类型

交叉类型是将多个类型合并为一个类型。这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。语法为: 类型一 & 类型二 。

以下是一个简单的示例:

interface Person1 {
  handsome: string,
}

interface Person2 {
  high: string,
}

type P1P2 = Person1 & Person2;

let p: P1P2 = { handsome: '帅', high: '高' }

交叉类型通常用于混入(Mixins)或其它不适合典型面向对象模型的地方。

TypeScript的联合类型

联合类型表示一个值可以是几种类型之一。我们用竖线( | )分隔每个类型,所以 number | string | boolean 表示一个值可以是 number , string ,或 boolean 。

以下是一个简单的示例:

function padLeft(value: string, padding: string | number) {
  // ...
}

在这个示例中,padding 参数可以是 string 或 number 类型。

TypeScript 中如何联合枚举类型的 Key?

你可以使用 TypeScript 中的 keyof typeof 来获取枚举键作为联合字符串的通用类型。例如,如果你有一个名为 MyEnum 的枚举,你可以使用以下代码来获取该枚举键的联合字符串类型:type MyEnumKeysAsStrings = keyof typeof MyEnum; // \"A\" | \"B\" | \"C\"

declare,declare global是什么?

在 TypeScript 中,declare 用于声明全局变量,函数和类等。declare global 用于扩展全局变量的类型和方法。