文章目录
1. 什么是 TypeScript?它与 JavaScript 有什么区别?
TypeScript 是一种由 Microsoft 开发的开源编程语言,它是 JavaScript 的一个超集,可以编译成纯 JavaScript。与 JavaScript 相比,TypeScript 引入了静态类型、类、接口等概念,以提供更好的代码可维护性、类型检查和开发体验。
TypeScript 的优势是什么?
- 静态类型检查: TypeScript 允许声明变量、函数等的类型,从而在开发过程中捕获潜在的类型错误。
- 代码可读性: 明确的类型声明使代码更易读懂和维护。
- 智能感知: TypeScript 提供了更好的 IDE 智能感知,增强了代码自动完成和提示功能。
- 重构支持: 类型信息可以帮助 IDE 在重构代码时更准确地识别变量和函数引用。
- 代码提示: 使用 TypeScript,您可以在开发过程中获得更多的代码提示和文档。
TypeScript 中的基本类型有哪些?
- number: 数字类型
- string: 字符串类型
- boolean: 布尔类型
- null 和 undefined: 用于表示为空值
- void: 表示没有返回值的函数
- any: 表示任意类型
- object: 表示非原始类型的类型
- array: 数组类型
- tuple: 元组类型
- enum: 枚举类型
2. TS 泛型、接口、泛型工具record、Pick、Omit
泛型:目的是在成员之间提供有意义的约束,这些成员可以是:类的实例成员、类的方法、函数参数和函数返回值。
Record:它用来生成一个属性为 K,类型为 T 的类型集合。
type Foo = Record<'a', string>
生成的对象key都为’a’,value只能为string类型
Pick:从 T 中将所有的 K 取出来,并生成一个新的类型。
const foo: Pick<IFoo, 'a'>
使用 Pick 生成的新类型只包含 a 属性
Omit:用来忽略 T 中的 K 属性
type UserWithoutEmail = Omit<User, 'email'>
忽略User中的email属性
3. TS unknow和any的区别,如何告诉编译器unknow一定是某个类型?
- any:任意类型,放弃了ts类型检查,允许对其进行任意操作
- unknow:暂时未知类型,之后仍然会进行ts检查,使用时需要进行类型检查或类型断言后才能进行操作,更加安全
unknow只能赋值unknow或any类型的值,而且无法读取任何属性和方法
let a:unknown = {a: 1}
let b:unknown = {b: 1}
a = b // 可以正常赋值
let c:number = 1
b = c // 正常
c = b // 报错
console.log(a.a) // 报错
将任何类型赋值给any类型的变量,并执行任何操作,和js相同。
将任何值赋值给unknow类型,但是需要进行类型检查或者断言才可以进行操作。
1.类型断言
let value: unknow = 'hello';
let length: number = (value as string).length;
2.类型判断
function func(value: unknow): void {
if (typeof value === 'string') {
console.log(value.toUpperCase())
} else if (Array.isArray(value)) {
console.log(value.length)
}
}
4. 元组与常规数组的区别
- TypeScript 中的元组是一个数组,其中元素的类型、顺序和数量已知。例如,[string, number] 元组类型期望第一个元素是字符串,第二个元素是数字。
- 常规数组只知道元素的类型,而不知道顺序或计数。
5. 什么是泛型,有什么作用?
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
function createArray<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray<string>(3, 'x'); // ['x', 'x', 'x']
泛型约束:在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法,此时可以对泛型进行约束
// 对泛型T进行了约束,一定含有一个length属性
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
loggingIdentity(7);
泛型作用:泛型可以用在函数、接口、类
泛型优点:
- 使用泛型的主要好处在于提高代码的复用性和灵活性。通过泛型,我们可以编写不特定数据类型的代码,使得这些代码可以适用于不同的数据类型。这样一来,我们不需要为每种数据类型编写重复的代码,从而减少了代码冗余。
- 泛型还可以增加代码的可读性和可维护性。当我们在编写泛型代码时,我们可以将代码逻辑和数据类型分离开来,使得代码更加清晰和易于理解。同时,泛型还可以在编译时进行类型检查,提前捕获潜在的类型错误,减少了运行时错误的可能性。
- 另外,泛型还使得我们可以更好地封装代码,隐藏内部实现细节。这样可以提高代码的安全性,并使得代码更易于维护和升级。
6. 什么是装饰器?
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上
是一种在不改变原类和使用继承的情况下,动态地扩展对象功能
同样的,本质也不是什么高大上的结构,就是一个普通的函数,@expression 的形式其实是Object.defineProperty的语法糖
expression求值后必须也是一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入
装饰器作用:类、方法/属性、参数、访问器
function addAge(constructor: Function) {
constructor.prototype.age = 18;
}
@addAge
class Person{
name: string;
age!: number;
constructor() {
this.name = 'huihui';
}
}
let person = new Person();
console.log(person.age); // 18
装饰器优点:
- 代码可读性变强了,装饰器命名相当于一个注释
- 在不改变原有代码情况下,对原来功能进行扩展
后面的使用场景中,借助装饰器的特性,除了提高可读性之后,针对已经存在的类,可以通过装饰器的特性,在不改变原有代码情况下,对原来功能进行扩展。
7. interface与type 有何区别
- 语法差异:
• interface 关键字用于声明接口,使用 interface 可以定义对象的形状、函数的签名等。
• type 关键字用于声明类型别名,可以给一个类型起一个新的名字。 - 合并能力:
• interface 具有合并能力,即同名的接口会自动合并为一个接口,合并后的接口会继承所有同名接口的成员。
• type 不具有合并能力,同名的类型别名会报错。 - 实现能力:
• interface 可以被类实现(使用 implements),用于类与接口的约束关系。
• type 不能被类实现,它只是给类型起别名,无法用于类与类型的约束关系。 - 扩展能力【继承】:
• interface 可以通过 extends 关键字扩展其他接口或类,实现接口的继承。
• type 可以使用交叉类型(&)或联合类型(|)组合多个类型来创建新的类型。 - 性能
interface > type - 声明对象
• interfaces只能描述 object shapes。
• type可用于其他类型,如原始类型(primitive),联合类型(union),交叉类型(intersection),元组等。
8. Object、object, {}有什么区别?
- Object:包含了所有类型,比如数字、布尔等
let obj:Object = 1
let obj2:Object = false
- object:非原始类型(字符串、数字、布尔…)的类型,包含所有引用类型
let obj:object = {a:1}
let obj1:object = 1 // 报错
- {}:等于new Object(),和Object一样,指所有类型
但是使用的时候无法进行赋值操作
let obj:{} = {a:1}
obj.b = 1 // 报错