文章目录
- 1. 什么是 TypeScript?它与 JavaScript 有什么区别?
- 2. TS 泛型、接口、泛型工具record、Pick、Omit
- 3. TS unknow和any的区别,如何告诉编译器unknow一定是某个类型?
- 4. 元组与常规数组的区别
- 5. 什么是泛型,有什么作用?
- 6. 什么是装饰器?
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检查,使用时需要进行类型检查或类型断言后才能进行操作,更加安全
将任何类型赋值给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
装饰器优点:
- 代码可读性变强了,装饰器命名相当于一个注释
- 在不改变原有代码情况下,对原来功能进行扩展
后面的使用场景中,借助装饰器的特性,除了提高可读性之后,针对已经存在的类,可以通过装饰器的特性,在不改变原有代码情况下,对原来功能进行扩展。